我有一些代码,我需要运行在不同的线程,而不是GUI,因为它目前导致窗体冻结,而代码运行(10秒左右)。
假设我以前从未创建过一个新线程;有什么简单/基本的例子,如何做到这一点在c#和使用。net Framework 2.0或更高版本?
我有一些代码,我需要运行在不同的线程,而不是GUI,因为它目前导致窗体冻结,而代码运行(10秒左右)。
假设我以前从未创建过一个新线程;有什么简单/基本的例子,如何做到这一点在c#和使用。net Framework 2.0或更高版本?
当前回答
在. net中有许多运行独立线程的方法,每种方法都有不同的行为。你需要在GUI退出后继续运行线程吗?您需要在线程和GUI之间传递信息吗?线程是否需要更新GUI?线程应该完成一个任务然后退出,还是继续运行?这些问题的答案会告诉你该使用哪种方法。
在Code Project网站上有一篇很好的异步方法文章,描述了各种方法并提供了示例代码。
注意,本文是在async/await模式和任务并行库引入。net之前编写的。
其他回答
乔·阿尔巴哈里是开始阅读的好地方。
如果你想创建自己的线程,这很简单:
using System.Threading;
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
/* run your code here */
Console.WriteLine("Hello, world");
}).Start();
将该代码放入一个函数中(不能与GUI在同一个线程上执行的代码),并执行以下代码来触发该代码的执行。
线程myThread=新线程(namefunction);
workerThread.Start();
在线程对象上调用start函数将导致在新线程中执行函数调用。
// 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();
但如果你阻止了,发出任何c调用又有什么意义呢?您也可以只使用同步调用。一个更好的选择是不阻塞,并传入一个lambda来进行清理:
nrgDel.BeginInvoke(lastRuntime,procDT,(ar)=> {ar.EndInvoke(ar);},null);
有一件事要记住,你必须调用EndInvoke。很多人忘记了这一点,最终泄露了WaitHandle,因为大多数异步实现在EndInvoke中释放了WaitHandle。
ThreadPool。QueueUserWorkItem对于简单的东西来说是非常理想的。唯一需要注意的是从另一个线程访问控件。
System.Threading.ThreadPool.QueueUserWorkItem(delegate {
DoSomethingThatDoesntInvolveAControl();
}, null);
又快又脏,但很管用:
用于顶部:
using System.Threading;
简单的代码:
static void Main( string[] args )
{
Thread t = new Thread( NewThread );
t.Start();
}
static void NewThread()
{
//code goes here
}
我只是将其放入一个新的控制台应用程序中作为示例