2020. 11. 23. 16:26
윈도우폼
c# 멀티스레드풀 기본소스
(2015년에 짠 코드라 그렇지 이미지처리를 CPU로 하는 병신짓은 하지말자)
using System.Collections;
public bool multi_threadpool_MC(float[,] img1f)
{
int img1wid = img1f.GetLength(0); // 기준 이미지 너비
int img1hei = img1f.GetLength(1); //기준 이미지 높이
int coreNum = 64; //스레드풀 갯수 설정
EventWaitHandle[] threadSig = new EventWaitHandle[coreNum]; //스레드풀 계산 완료 시그널
Hashtable[] ht_t = new Hashtable[coreNum];
for (int i = 0; i < coreNum; i++)
{
threadSig[i] = new EventWaitHandle(false, EventResetMode.ManualReset);//서브스레드 대기 시그널 생성
ht_t[i] = new Hashtable(); //인자를 전달할 해쉬테이블 생성
ht_t[i]["num"] = i;
ht_t[i]["coreNum"] = coreNum; //인자 박싱
ht_t[i]["threadSig"] = threadSig[i];
ht_t[i]["img1f"] = img1f; //계산처리할 데이터
ht_t[i]["return"] = false; //반환값
ThreadPool.QueueUserWorkItem(image_search_MC_thread, ht_t[i]);
}
WaitHandle.WaitAll(threadSig); //스레드 처리 완료 대기(최대 64개)
/*
혹은
for (i=0; i<coreNum; i++)
{
threadSig[i].WaitOne();//스레드 처리 완료 대기
}
*/
bool _return_t = false;
for (int i = 0; i < core_num; i++)
{
_return_t = _return_t || (bool)ht_t[i]["return"];
}
return _return_t;
}
private static void image_search_MC_thread(object hashtable_var)
{
Hashtable ht = (Hashtable)hashtable_var; //오브젝트 언박싱
int num = (int)ht["num"];
int core_num = (int)ht["coreNum"];
float[,] img1f = (float[,])ht["img1f"]; //해시테이블 언박싱
int img1wid = img1f.GetLength(0); //1번째 차원 길이
int img1hei = img1f.GetLength(1); //2번째 차원 길이
for (int i = num; i < img1wid; i += core_num) //분산처리
{
for (int j = 0; j < img1hei; j++)
{
if (i==j) // 반환된 값이 True일 경우
{
ht["return"] = true;
}
}
}
//ht["return"] = false;
((EventWaitHandle)ht["_thread_sig"]).Set();
}
심플버전
using UnityEngine;
using System.Collections;
using System.Threading; //스레드 시스템을 호출
using System; //스레드에서 계산을 위해 닷넷 시스템 호출
public class MultiThread : MonoBehaviour
{
private Thread thread;
private EventWaitHandle threadSig;
void Awake()
{
threadSig = new EventWaitHandle(false, EventResetMode.ManualReset);//서브스레드 대기 시그널 생성
thread = new Thread(SubThread); //스레드를 생성
thread.IsBackground = true; //백그라운드에서 동작(메인스레드의 하위로 들어감)
thread.Start(); //스레드 시작
//기다리는동안 처리될코드
threadSig.WaitOne();//서브스레드 처리 완료 대기중
threadSig.Reset();//수신완료 리셋
}
private void SubThread()
{
//여기에 처리시킬 코드를 넣습니다
threadSig.Set(); //서브스레드 종료알림
}
}
멀티스레드 기본소스
//ver 0.1.2
using UnityEngine;
using System.Collections;
using System.Threading; //스레드 시스템을 호출
using System; //스레드에서 계산을 위해 닷넷 시스템 호출
public class multi_thread : MonoBehaviour {
private Thread[] _thread;
private EventWaitHandle[] _thread_sig;
private EventWaitHandle _thread_sig_main ;
private EventWaitHandle _thread_sig_end ;
public int _core_num = SystemInfo.processorCount*16; //코어갯수 설정(코어갯수*16)
private int i, j, k, l; //반복문용 변수 설정
// Use this for initialization
void Awake() {
_thread = new Thread[_core_num]; //코어갯수에 맞게 스레드 생성
_thread_sig = new EventWaitHandle[_core_num]; //코어갯수에 맞게 핸들생성
_thread_sig_main=new EventWaitHandle(false,EventResetMode.ManualReset); //메인스레드 처리 완료 알림 시그널 생성
_thread_sig_end=new EventWaitHandle(false,EventResetMode.ManualReset); //메인스레드 수신완료 시그널 생성
for(i=0;i<_core_num;i++)
{
_thread_sig[i]=new EventWaitHandle(false,EventResetMode.ManualReset);//서브스레드 대기 시그널 생성
_thread[i] = new Thread (subthread); //스레드를 생성
_thread[i].IsBackground = true; //백그라운드에서 동작(메인스레드의 하위로 들어감)
//_thread[i].Priority = ThreadPriority.Highest; //백그라운드 스레드의 우선순위를 높음으로 변경(높을수록 빠름)
//_thread[i].Priority = ThreadPriority.AboveNormal; //백그라운드 스레드의 우선순위를 약간 높음으로 변경
//_thread[i].Priority = ThreadPriority.Normal; //백그라운드 스레드의 우선순위를 보통으로 변경
_thread[i].Priority = ThreadPriority.BelowNormal; //백그라운드 스레드의 우선순위를 약간 낮음으로 변경
//_thread[i].Priority = ThreadPriority.Lowest; //백그라운드 스레드의 우선순위를 낮음으로 변경(낮을수록 느림)
_thread[i].Start (i); //스레드 시작
}
}
// Update is called once per frame
void LateUpdate ()
{
_thread_sig_end.Reset();//수신완료 리셋
_thread_sig_main.Set();//메인스레드 처리 완료 알림(서브스레드 시작)
for (i=0; i<_core_num; i++)
{
_thread_sig[i].WaitOne();//서브스레드 처리 완료 대기중
}
_thread_sig_main.Reset();//메인스레드 처리중 알림
_thread_sig_end.Set();//메인스레드 수신 완료 알림
}
private void subthread(object _thread_num)
{
int _t_thread_num=(int)_thread_num; //스레드 번호 인자를 넘겨받은것을 언박싱
while(true)
{
_thread_sig_main.WaitOne(); //메인스레드가 종료할때까지 대기
/*
여기에 처리시킬 코드를 넣습니다
예시
for (int i=_t_thread_num; i<100000; i+=_core_num)
{
_t += i;
}
*/
_thread_sig[_t_thread_num].Set(); //서브스레드 종료알림
_thread_sig_end.WaitOne(); //메인스레드가 수신했는지
_thread_sig[_t_thread_num].Reset(); //서브스레드 재가동 알림
}
}
일반함수처럼 쓸수있는 스레드. (태스크)
test(); 같은식으로 호출해주면 됨
비동기로 작동한다
주의점은 유니티가 종료되어도 계속 작동해서 가급적 코루틴을 쓰자
async void test()
{
await Task.Run(() => {
while (true)
{
System.Threading.Thread.Sleep(1000);
Debug.Log($"테스트 {System.DateTime.Now}");
}
});
}
태스크, 코루틴이랑 비슷하지만 유니티가 종료되어도 계속 작동한다
유니티 함수계열은 안 된다(디버그로그는 된다)
var t = System.Threading.Tasks.Task.Run(() => {
//System.Threading.Tasks.Task.Delay(10000).Wait();
System.Threading.Thread.Sleep(10000);
Debug.Log("Task ended delay...");
});
반환값이 있는 태스크
주의점은 result호출시 계산이 끝날때까지 기다린다
Debug.Log($"Start {System.DateTime.Now}");
var t = System.Threading.Tasks.Task.Run(() => {
System.Threading.Thread.Sleep(10000);
Debug.Log($"Task ended delay... {System.DateTime.Now}");
});
var t2 = System.Threading.Tasks.Task.Run(() => {
System.Threading.Thread.Sleep(3000);
return System.DateTime.Now;
});
Debug.Log($"Task2 ended delay...{t2.Result}"); //result구하면서 wait가 걸린다
'윈도우폼' 카테고리의 다른 글
윈폼 키보드마우스 (0) | 2021.01.17 |
---|---|
자주 쓰는 윈폼 코드 모음 (0) | 2020.10.31 |
c# 윈도우 폼 (0) | 2018.01.28 |