当我开发多个较小的应用程序时,我注意到我可以在这里或那里使用新线程来执行后台任务。我尝试了一些选项,主要是背景工作者和代表。我想要做的是有一个专用的线程类来运行我的所有线程,我可以在多个程序中重复使用。
我正在寻找有关在这种情况下阅读或查看或我应该做什么的指导。
我现在失败的例子:
主线程(GUI)启动 用户单击按钮1,该按钮通过一些逻辑并启动多个任务密集型计算(这会冻结GUI直到计算完成)。
我想做的事情就是......
主线程(GUI)启动 用户单击button1,创建在某种列表中排队的线程 GUI线程报告进度作为线程进程计算 线程完成并稍后出列 (可能?)在后台有线程类循环,等待项目入队和处理。
我用于较小任务的典型方法是
Thread fooThread= new Thread((ThreadStart)delegate
{
//command
});
fooThread.Start();
问题是,我的按钮事件中还有其他项目(也许我应该重构它们?)
样品
private void btnCopy_Click( object sender, EventArgs e )
{
//check file exists, check destination exists, etc
//start new thread
Thread fooThread= new Thread((ThreadStart)delegate
{
//copy files to destination using method foobarCopy(params)
});
fooThread.Start();
//if file copy is successful, inform user on GUI.
}
我主要使用.NET2.0,但可以根据需要提升到4.5。
答案 0 :(得分:0)
将您的应用程序升级到.Net 4.5,您将会感到轻松自在。您将能够利用await-async构造利用任务和任务并行库(TPL)基础结构。
在.Net的今天,您必须有非常令人信服的理由,为什么要手动创建自己的线程而不是利用现有的线程池。其中一个原因可能是,如果您寻求绝对控制在您的流程中创建的新线程,原因如下所述,但不限于:
对于典型的业务线应用程序,您几乎不需要对线程进行如此多的精细控制。
因此,Tasks是您最好的朋友,可以帮助您摆脱冻结的UI问题。您可以查看我的博客here了解更多详情。以下是我将如何重写代码:
private async void btnCopy_Click(object sender, EventArgs e)
{
//check file exists, check destination exists, etc
string sourceFile = @"C:\a.txt", destinationFile = @"C:\b.txt";
//Let TPL do the heavy lifting of interacting with disk for I/O
var copyTask = await CopyFile(sourceFile, destinationFile);
/*
//Manual thread instantiation not needed. Hence commented
Thread fooThread = new Thread((ThreadStart)delegate
{
//copy files to destination using method foobarCopy(params)
});
fooThread.Start();
*/
//if file copy is successful, inform user on GUI.
if (copyTask)
{
//show a message box
}
}
private async Task<bool> CopyFile(string sourceFile, string destinationFile)
{
bool fileCopiedSuccessfully = true;
//here use async I/O methods from stream class which support the notion of tasks
try
{
using (FileStream sourceStream = File.Open(sourceFile, FileMode.Open))
{
using (FileStream destinationStream = File.Create(destinationFile))
{
//exactly at this point of time when the actual copy happens your GUI thread is completely
//free to do anything. It won't freeze.
//This work happens on a thread-pool thread which you don't have to worry about.
await sourceStream.CopyToAsync(destinationStream);
}
}
}
catch (IOException ioex)
{
fileCopiedSuccessfully = false;
MessageBox.Show("An IOException occured during copy, " + ioex.Message);
}
catch (Exception ex)
{
fileCopiedSuccessfully = false;
MessageBox.Show("An Exception occured during copy, " + ex.Message);
}
return fileCopiedSuccessfully ;
}