C# 如何在新线程中运行一些简单的代码?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/363377/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I run a simple bit of code in a new thread?
提问by
I have a bit of code that I need to run in a different thread than the GUI as it currently causes the form to freeze whilst the code runs (10 seconds or so).
我有一些代码需要在与 GUI 不同的线程中运行,因为它当前会导致表单在代码运行时冻结(10 秒左右)。
Assume I have never created a new thread before; what's a simple/basic example of how to do this in C# and using .NET Framework 2.0 or later?
假设我以前从未创建过新线程;关于如何在 C# 中使用 .NET Framework 2.0 或更高版本执行此操作的简单/基本示例是什么?
回答by Andy
Try using the BackgroundWorkerclass. You give it delegates for what to run, and to be notified when work has finished. There is an example on the MSDN page that I linked to.
尝试使用BackgroundWorker类。你给它委托来运行什么,并在工作完成时得到通知。我链接到的 MSDN 页面上有一个示例。
回答by FallenAvatar
Quick and dirty, but it will work:
又快又脏,但它会起作用:
Using at top:
在顶部使用:
using System.Threading;
simple code:
简单代码:
static void Main( string[] args )
{
Thread t = new Thread( NewThread );
t.Start();
}
static void NewThread()
{
//code goes here
}
I just threw this into a new console application for an exmaple
我只是把它放到一个新的控制台应用程序中作为例子
回答by Mark Brackett
The ThreadPool.QueueUserWorkItemis pretty ideal for something simple. The only caveat is accessing a control from the other thread.
该ThreadPool.QueueUserWorkItem是相当理想的简单的东西。唯一需要注意的是从另一个线程访问控件。
System.Threading.ThreadPool.QueueUserWorkItem(delegate {
DoSomethingThatDoesntInvolveAControl();
}, null);
回答by Redbaron
Put that code in a function (the code that can't be executed on the same thread as the GUI), and to trigger that code's execution put the following.
将该代码放在一个函数中(不能在与 GUI 相同的线程上执行的代码),并触发该代码的执行放置以下内容。
Thread myThread= new Thread(nameOfFunction);
Thread myThread= new Thread(nameOfFunction);
workerThread.Start();
workerThread.Start();
Calling the start function on the thread object will cause the execution of your function call in a new thread.
在线程对象上调用 start 函数将导致在新线程中执行您的函数调用。
回答by Charles Bretana
another option, that uses delegates and the Thread Pool...
另一种选择,使用委托和线程池...
assuming 'GetEnergyUsage' is a method that takes a DateTime and another DateTime as input arguments, and returns an Int...
假设 '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);
回答by IgorK
How to: Use a Background Thread to Search for Files
You have to be very carefull with access from other threads to GUI specific stuff (it is common for many GUI toolkits). If you want to update something in GUI from processing thread check this answerthat I think is useful for WinForms. For WPF see this(it shows how to touch component in UpdateProgress() method so it will work from other threads, but actually I don't like it is not doing CheckAccess()
before doing BeginInvoke
through Dispathcer, seeand search for CheckAccess in it)
您必须非常小心地从其他线程访问 GUI 特定的东西(这对于许多 GUI 工具包来说很常见)。如果您想从处理线程中更新 GUI 中的某些内容,请检查我认为对 WinForms 有用的答案。对于 WPF,请参阅此内容(它显示了如何在 UpdateProgress() 方法中触摸组件,以便它可以从其他线程工作,但实际上我不喜欢它CheckAccess()
在BeginInvoke
通过 Dispathcer执行之前不这样做,请参阅并在其中搜索 CheckAccess)
Was looking .NET specific book on threading and found this one(free downloadable). See http://www.albahari.com/threading/for more details about it.
正在寻找有关线程的 .NET 特定书籍并找到了这本(可免费下载)。有关它的更多详细信息,请参阅http://www.albahari.com/threading/。
I believe you will find what you need to launch execution as new thread in first 20 pages and it has many more (not sure about GUI specific snippets I mean strictly specific to threading). Would be glad to hear what community thinks about this work 'cause I'm reading this one. For now looked pretty neat for me (for showing .NET specific methods and types for threading). Also it covers .NET 2.0 (and not ancient 1.1) what I really appreciate.
我相信您会在前 20 页中找到作为新线程启动执行所需的内容,并且还有更多内容(不确定 GUI 特定片段,我的意思是严格特定于线程)。很高兴听到社区对这项工作的看法,因为我正在阅读这篇文章。现在对我来说看起来很整洁(用于显示 .NET 特定的线程方法和类型)。它还涵盖了我真正欣赏的 .NET 2.0(而不是古老的 1.1)。
回答by Dour High Arch
There are many ways of running separate threads in .Net, each has different behaviors. Do you need to continue running the thread after the GUI quits? Do you need to pass information between the thread and GUI? Does the thread need to update the GUI? Should the thread do one task then quit, or should it continue running? The answers to these questions will tell you which method to use.
在 .Net 中有多种运行独立线程的方法,每种方法都有不同的行为。GUI退出后是否需要继续运行线程?是否需要在线程和 GUI 之间传递信息?线程是否需要更新 GUI?线程应该完成一项任务然后退出,还是应该继续运行?这些问题的答案将告诉您使用哪种方法。
There is a good async method articleat the Code Project web site that describes the various methods and provides sample code.
Code Project 网站上有一篇很好的异步方法文章,描述了各种方法并提供了示例代码。
Note this article was written before the async/awaitpattern and Task Parallel Librarywere introduced into .NET.
请注意,本文是在async/await模式和任务并行库引入 .NET之前编写的。
回答by Matt Davison
// 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);
Charles your code(above) is not correct. You do not need to spin wait for completion. EndInvoke will block until the WaitHandle is signaled.
查尔斯您的代码(以上)不正确。您不需要旋转等待完成。EndInvoke 将阻塞,直到 WaitHandle 发出信号。
If you want to block until completion you simply need to
如果你想阻塞直到完成,你只需要
nrgDel.EndInvoke(nrgDel.BeginInvoke(lastRuntime,procDT,null,null));
or alternatively
或者
ar.AsyncWaitHandle.WaitOne();
But what is the point of issuing anyc calls if you block? You might as well just use a synchronous call. A better bet would be to not block and pass in a lambda for cleanup:
但是,如果您阻塞,发出 anyc 调用的意义何在?您也可以只使用同步调用。更好的选择是不阻塞并传入 lambda 进行清理:
nrgDel.BeginInvoke(lastRuntime,procDT,(ar)=> {ar.EndInvoke(ar);},null);
One thing to keep in mind is that you mustcall EndInvoke. A lot of people forget this and end up leaking the WaitHandle as most async implementations release the waithandle in EndInvoke.
要记住的一件事是您必须调用 EndInvoke。很多人忘记了这一点并最终泄漏了 WaitHandle,因为大多数异步实现在 EndInvoke 中释放了等待句柄。
回答by user50612
If you are going to use the raw Thread object then you need to set IsBackground to true at a minimum and you should also set the Threading Apartment model (probably STA).
如果您打算使用原始线程对象,那么您至少需要将 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()
}
I would recommend the BackgroundWorker class if you need UI interaction.
如果您需要 UI 交互,我会推荐 BackgroundWorker 类。
回答by Robert Paulson
I'd recommend looking at Jeff Richter's Power Threading Libraryand specifically the IAsyncEnumerator. Take a look at the video on Charlie Calvert'sblog where Richter goes over it for a good overview.
我建议查看 Jeff Richter 的Power Threading Library,特别是 IAsyncEnumerator。看一看Charlie Calvert博客上的视频,Richter 对其进行了很好的概述。
Don't be put off by the name because it makes asynchronous programming tasks easier to code.
不要被这个名字吓倒,因为它使异步编程任务更容易编码。