Get it on Google Play


Wm뮤 :: c# 멀티스레드 기본소스

블로그 이미지
가끔 그림그리거나 3D모델링하거나
취미로 로봇만드는
퇴직한 전자과 게임프로그래머
2020.3.48f1 , 2022.3.6f1 주로 사용
모카쨩
@Ahzkwid

Recent Comment

Archive


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
posted by 모카쨩

  • total
  • today
  • yesterday

Recent Post

저사양 유저용 블로그 진입