【问题标题】:Creating A Class to Handle Threads创建一个类来处理线程
【发布时间】:2017-05-09 14:04:41
【问题描述】:

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

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

我现在失败的例子:

主线程 (GUI) 启动 用户单击按钮 1,该按钮会执行一些逻辑并启动多个任务密集型计算(这将冻结 GUI,直到计算完成)。

我想做的是诸如......

主线程 (GUI) 启动 用户单击按钮 1 创建在某种列表中排队的线程 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。

【问题讨论】:

  • 你的按钮点击代码应该是你的类。 FileCopier 或带有Start() 的任何内容。确定它是否完成并且通知取决于您,但这确实是您的课程。我不确定您是否需要创建自己的线程管理器类,而是将该代码重构为业务对象,从那里您至少可以看到可以为您重构的下一个基类制作什么。
  • 听起来你最好使用现有的线程池支持。
  • 也许您应该使用异步回调方法来操作 gui 的结果,或者您可以使用面向方面的框架检查或控制您的逻辑、数据等,例如 spring.net aop。

标签: c# .net wpf windows multithreading


【解决方案1】:

将您的应用程序升级到 .Net 4.5,您就放心了。您将能够利用具有等待异步构造的任务和任务并行库 (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 ;
}

【讨论】:

    猜你喜欢
    • 2013-02-08
    • 1970-01-01
    • 1970-01-01
    • 2021-05-08
    • 1970-01-01
    • 1970-01-01
    • 2021-06-07
    • 2013-12-02
    • 1970-01-01
    相关资源
    最近更新 更多