创建一个处理线程的类

时间:2016-12-23 22:53:29

标签: c# .net wpf windows multithreading

当我开发多个较小的应用程序时,我注意到我可以在这里或那里使用新线程来执行后台任务。我尝试了一些选项,主要是背景工作者和代表。我想要做的是有一个专用的线程类来运行我的所有线程,我可以在多个程序中重复使用。

我正在寻找有关在这种情况下阅读或查看或我应该做什么的指导。

我现在失败的例子:

主线程(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。

1 个答案:

答案 0 :(得分:0)

将您的应用程序升级到.Net 4.5,您将会感到轻松自在。您将能够利用await-async构造利用任务和任务并行库(TPL)基础结构。

在.Net的今天,您必须有非常令人信服的理由,为什么要手动创建自己的线程而不是利用现有的线程池。其中一个原因可能是,如果您寻求绝对控制在您的流程中创建的新线程,原因如下所述,但不限于:

  • 何时应该创建我的主题?
  • 我的流程中应该创建多少个新线程?
  • 什么时候应该处理我的帖子?
  • 从OS调度算法的角度来看,新线程的优先级应该是什么?例如高,中,低
  • 我的线程应该是后台线程还是前台线程?

对于典型的业务线应用程序,您几乎不需要对线程进行如此多的精细控制。

因此,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 ;
}