새 스레드에서 간단한 코드를 실행하려면 어떻게 해야 합니까?
현재 GUI와는 다른 스레드에서 실행해야 하는 코드가 있는데, 이는 코드가 실행되는 동안(10초 정도) 폼이 고정되기 때문입니다.
C#에서 .NET Framework 2.0 이상을 사용하여 새 스레드를 생성한 적이 없다고 가정해 보겠습니다.
고유한 스레드를 생성하려면 다음과 같이 간단하게 수행할 수 있습니다.
using System.Threading;
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
/* run your code here */
Console.WriteLine("Hello, world");
}).Start();
BackgroundWorker
당신에게 최선의 선택인 것 같습니다.
여기 제 최소한의 예가 있습니다.버튼을 클릭하면 백그라운드 작업자가 백그라운드 스레드에서 작업을 시작하고 동시에 진행 상황을 보고합니다.또한 작업이 완료된 후에 보고할 것입니다.
using System.ComponentModel;
...
private void button1_Click(object sender, EventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
// this allows our worker to report progress during work
bw.WorkerReportsProgress = true;
// what to do in the background thread
bw.DoWork += new DoWorkEventHandler(
delegate(object o, DoWorkEventArgs args)
{
BackgroundWorker b = o as BackgroundWorker;
// do some simple processing for 10 seconds
for (int i = 1; i <= 10; i++)
{
// report the progress in percent
b.ReportProgress(i * 10);
Thread.Sleep(1000);
}
});
// what to do when progress changed (update the progress bar for example)
bw.ProgressChanged += new ProgressChangedEventHandler(
delegate(object o, ProgressChangedEventArgs args)
{
label1.Text = string.Format("{0}% Completed", args.ProgressPercentage);
});
// what to do when worker completes its task (notify the user)
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
delegate(object o, RunWorkerCompletedEventArgs args)
{
label1.Text = "Finished!";
});
bw.RunWorkerAsync();
}
참고:
- 단순성을 위해 C#의 익명 방법을 사용하여 모든 것을 단일 방법으로 넣었지만, 항상 다른 방법으로 끌어낼 수 있습니다.
- 다음 내에서 GUI를 업데이트하는 것이 안전합니다.
ProgressChanged
또는RunWorkerCompleted
그러중다음서에DoWork
유할것의 원인이 될 입니다.InvalidOperationException
.
스레드 풀.QueueUserWorkItem은 간단한 것에 매우 이상적입니다.유일한 경고는 다른 스레드에서 컨트롤에 액세스하는 것입니다.
System.Threading.ThreadPool.QueueUserWorkItem(delegate {
DoSomethingThatDoesntInvolveAControl();
}, null);
다음은 다른 옵션입니다.
Task.Run(()=>{
//Here is a new thread
});
빠르고 지저분하지만 효과가 있습니다.
맨 위에서 사용:
using System.Threading;
단순 코드:
static void Main( string[] args )
{
Thread t = new Thread( NewThread );
t.Start();
}
static void NewThread()
{
//code goes here
}
예를 들어 새로운 콘솔 애플리케이션에 이 기능을 적용했습니다.
BackgroundWorker 클래스를 사용해 보십시오.딜러에게 무엇을 실행할 것인지, 작업이 완료되면 알림을 받을 것인지를 알려줍니다.제가 링크한 MSDN 페이지에 예시가 있습니다.
값을 얻으려면 다음을 수행합니다.
var someValue;
Thread thread = new Thread(delegate()
{
//Do somthing and set your value
someValue = "Hello World";
});
thread.Start();
while (thread.IsAlive)
Application.DoEvents();
함수(GUI와 동일한 스레드에서 실행할 수 없는 코드)에 코드를 넣고 해당 코드의 실행을 트리거하려면 다음을 입력합니다.
Thread myThread= new Thread(nameOfFunction);
workerThread.Start();
스레드 개체에서 시작 함수를 호출하면 새 스레드에서 함수 호출이 실행됩니다.
여기서는 progressBar가 있는 스레드를 사용하는 방법을 설명합니다. 이는 스레드가 작동하는 방식을 이해하기 위한 것입니다. 여기에는 3개의 progressBar와 4개의 버튼이 있습니다.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Thread t, t2, t3;
private void Form1_Load(object sender, EventArgs e)
{
CheckForIllegalCrossThreadCalls = false;
t = new Thread(birinicBar); //evry thread workes with a new progressBar
t2 = new Thread(ikinciBar);
t3 = new Thread(ucuncuBar);
}
public void birinicBar() //to make progressBar work
{
for (int i = 0; i < 100; i++) {
progressBar1.Value++;
Thread.Sleep(100); // this progressBar gonna work faster
}
}
public void ikinciBar()
{
for (int i = 0; i < 100; i++)
{
progressBar2.Value++;
Thread.Sleep(200);
}
}
public void ucuncuBar()
{
for (int i = 0; i < 100; i++)
{
progressBar3.Value++;
Thread.Sleep(300);
}
}
private void button1_Click(object sender, EventArgs e) //that button to start the threads
{
t.Start();
t2.Start(); t3.Start();
}
private void button4_Click(object sender, EventArgs e)//that button to stup the threads with the progressBar
{
t.Suspend();
t2.Suspend();
t3.Suspend();
}
private void button2_Click(object sender, EventArgs e)// that is for contuniue after stuping
{
t.Resume();
t2.Resume();
t3.Resume();
}
private void button3_Click(object sender, EventArgs e) // finally with that button you can remove all of the threads
{
t.Abort();
t2.Abort();
t3.Abort();
}
}
원시 스레드 개체를 사용하려면 IsBackground를 최소 true로 설정해야 하며 스레드화 아파트 모델(아마도 STA)도 설정해야 합니다.
public static void DoWork()
{
// do some work
}
public static void StartWorker()
{
Thread worker = new Thread(DoWork);
worker.IsBackground = true;
worker.SetApartmentState(System.Threading.ApartmentState.STA);
worker.Start()
}
UI 상호 작용이 필요하다면 BackgroundWorker 클래스를 추천합니다.
// following declaration of delegate ,,,
public delegate long GetEnergyUsageDelegate(DateTime lastRunTime,
DateTime procDateTime);
// following inside of some client method
GetEnergyUsageDelegate nrgDel = GetEnergyUsage;
IAsyncResult aR = nrgDel.BeginInvoke(lastRunTime, procDT, null, null);
while (!aR.IsCompleted) Thread.Sleep(500);
int usageCnt = nrgDel.EndInvoke(aR);
찰스님의 코드(위)가 올바르지 않습니다.완료될 때까지 대기를 회전시킬 필요는 없습니다.EndInvoke는 WaitHandle이 표시될 때까지 차단됩니다.
완료될 때까지 차단하려면 다음 작업만 수행하면 됩니다.
nrgDel.EndInvoke(nrgDel.BeginInvoke(lastRuntime,procDT,null,null));
또는 그 대신에
ar.AsyncWaitHandle.WaitOne();
하지만 당신이 차단한다면 anyc calls를 발행하는 이유가 무엇입니까?당신은 그냥 동기식 통화를 사용하는 것이 나을 수도 있습니다.더 나은 방법은 정리를 위해 람다를 차단하고 전달하지 않는 것입니다.
nrgDel.BeginInvoke(lastRuntime,procDT,(ar)=> {ar.EndInvoke(ar);},null);
한 가지 명심해야 할 것은 EndInvoke를 호출해야 한다는 것입니다.대부분의 비동기 구현이 EndInvoke의 wait 핸들을 릴리스함에 따라 많은 사람들이 이것을 잊고 WaitHandle을 유출하게 됩니다.
딜러와 스레드 풀을 사용하는 다른 옵션...
'GetEnergyUsage'가 DateTime과 다른 DateTime을 입력 인수로 사용하고 Int...를 반환하는 메서드라고 가정합니다.
// following declaration of delegate ,,,
public delegate long GetEnergyUsageDelegate(DateTime lastRunTime,
DateTime procDateTime);
// following inside of some client method
GetEnergyUsageDelegate nrgDel = GetEnergyUsage;
IAsyncResult aR = nrgDel.BeginInvoke(lastRunTime, procDT, null, null);
while (!aR.IsCompleted) Thread.Sleep(500);
int usageCnt = nrgDel.EndInvoke(aR);
에서 별도의 스레드를 실행하는 방법은 여러 가지가 있습니다.넷, 각각 다른 행동을 합니다.GUI가 종료된 후에도 스레드를 계속 실행해야 합니까?스레드와 GUI 간에 정보를 전달해야 합니까?스레드가 GUI를 업데이트해야 합니까?스레드가 한 가지 작업을 수행한 후 종료해야 합니까, 아니면 계속 실행해야 합니까?이러한 질문에 대한 답변을 통해 어떤 방법을 사용해야 하는지 알 수 있습니다.
Code Project 웹사이트에는 다양한 방법을 설명하고 샘플 코드를 제공하는 좋은 비동기 방법 기사가 있습니다.
이 문서는 비동기/대기 패턴 및 작업 병렬 라이브러리가 .NET에 도입되기 전에 작성되었습니다.
다른 스레드에서 GUI 관련 항목에 액세스할 때는 매우 주의해야 합니다(많은 GUI 툴킷에서 흔히 볼 수 있음).처리 스레드에서 GUI를 업데이트하려면 WinForms에 유용하다고 생각되는 이 답변을 확인하십시오.WPF의 경우 이것을 참조하십시오(UpdateProgress() 메서드에서 구성 요소를 터치하여 다른 스레드에서 작동하는 방법을 보여주지만 실제로는 그렇지 않습니다.CheckAccess()
BeginInvoke
Dispatcher를 통해 CheckAccess를 확인하고 검색합니다.)
스레드화에 대한 .NET 특정 책을 찾고 있었는데 이 책(무료 다운로드 가능)을 발견했습니다.자세한 내용은 http://www.albahari.com/threading/ 을 참조하십시오.
저는 당신이 처음 20페이지에서 새로운 스레드로 실행을 시작하는 데 필요한 것을 찾을 것이라고 믿습니다. 그리고 그것은 더 많은 것을 가지고 있습니다(스레드에 엄격하게 특정된 GUI 특정 스니펫에 대해서는 확실하지 않습니다).이 작품에 대한 지역사회의 생각을 들으면 기쁠 것 같습니다. 왜냐하면 저는 이 작품을 읽고 있기 때문입니다.지금은 (스레드를 위한 .NET 고유의 방법과 유형을 보여주기 위한) 꽤 깔끔해 보입니다.또한 .NET 2.0(고대 1.1이 아님)에 대해서도 설명합니다.
저는 제프 리히터의 파워 스레딩 라이브러리, 특히 IAsyncEnumerator를 보는 것을 추천합니다.Charlie Calvert의 블로그에서 Richter가 좋은 개요를 위해 검토하는 비디오를 보세요.
이 이름을 사용하면 비동기 프로그래밍 작업을 코드화하기 쉽기 때문에 이 이름을 무시하지 마십시오.
언급URL : https://stackoverflow.com/questions/363377/how-do-i-run-a-simple-bit-of-code-in-a-new-thread
'programing' 카테고리의 다른 글
트리거 본문에서 동일한 테이블에 대한 다른 삭제를 포함하는 삭제 후 트리거를 작성하는 방법은 무엇입니까? (0) | 2023.06.27 |
---|---|
반환 매개 변수를 사용하여 최대 절전 모드에서 오라클 함수를 호출하는 방법은 무엇입니까? (0) | 2023.06.27 |
왜 글로벌 변수는 사악한가요? (0) | 2023.06.27 |
유형 스크립트에서 값으로 지도를 "필터링"할 수 있습니까? (0) | 2023.06.27 |
Vuex 스토어에서 매개 변수를 사용하여 시작할 때 구성 요소에서 데이터 가져오기 (0) | 2023.06.27 |