【问题标题】:What are the different ways of implementing multithreading in .net在.net中实现多线程的不同方法是什么
【发布时间】:2010-04-07 19:22:02
【问题描述】:

我这几天一直在与多线程作斗争。

我不明白multithreading 有什么不同的方式。我已经阅读了一些关于backgroundWorker 的内容,以及一些关于创建线程对象的内容。 昨天在delegate的例子中看到通过调用BeginInvoke实现多线程。

我不明白multithreading 的这些不同方式还是在同一个背景类上工作的方式相同。 请帮我说清楚。

【问题讨论】:

    标签: .net multithreading backgroundworker begininvoke conceptual


    【解决方案1】:

    我非常喜欢这个explanations。也许他们也能帮助你。
    然后,还有 Jon Skeet 的 this article

    【讨论】:

    • 这是很好的解释,也是本书的一部分。写的真好。
    【解决方案2】:

    任何没有 GUI 的线程都是后台工作线程。 在 dot net 上,使用线程的常用方法是创建一个线程对象并给它一个线程 main 方法,所以这个函数将在后台执行 首先我认为您应该阅读以下书籍以更深入地了解该主题

    • .NET 多线程
    • C# 线程手册

    另外在一个 GUI 应用程序上,如 WPF 或 win form 应用程序,唯一可以改变 gui 元素的线程是主线程(gui 线程),所以你应该使用 begininvoke 使用这个线程并放一个回调来改变gui,否则你会得到一个无效的操作异常。

    使用线程的另一种方法是使用 .net 的线程池,例如这些

       ThreadPool.QueueUserWorkItem(new WaitCallback(delegateMethod), data);
    
     private void delegateMethod(object data){
       //some stuff
     }
    

    【讨论】:

      【解决方案3】:

      首先,我要说的是,除非绝对必要,否则不要使用多线程。尝试以最熟练的方式避免和优化您的代码将取得最佳效果,因为您将避免多线程问题。

      其次,BackgroundWorker 类是一个好的开始。您将需要实例化尽可能多的实例,因为您需要运行线程。对于它们中的每一个,您都必须编写其DoWork() 方法。此方法在您通过调用BackgroundWorker.RunWorkerAsync() 方法启动其操作时调用。您要放置在 DoWork() 事件中的代码是在应用程序的主线程忙于其他事情时应在后台异步运行的代码。其他两个事件:ProgressChanged()RunWorkerCompleted() 用于 ReportProgress() 或定义线程完成工作时要做什么,无论它是什么结束(异常,正确结束等)我大部分使用 BackgroundWorker在我看来,时间是最简单的。

      第三,您可以使用System.Threading.Thread 类。它比仅仅定义一个 DoWork() 事件并通过调用另一个方法使其发生要复杂一些。您必须熟悉delegates。简而言之,委托是用于在后台执行某些工作的方法或函数的类型。至于这些委托,你可能有多个相同委托类型的方法,就像我刚才说的,委托是方法类型。您可能有多个delegate 的引用。您也可以将其视为方法签名。然后,当需要使用它时,您必须为想要的委托引用一个方法。使用 System.Threading.Thread 类,您需要留意ThreadStart delegate

      delegate void DoWork(object sender);
      
      private void btnProcessWork_Click(object sender, EventArgs e) {
          DoWork doWork = SimpleDoWorkMethod;
          // Then start using the delegate.
          Thread t = new Thread(new ThreadStart(doWork));
          t.Start(); // Launch the thread in background...
          // Do something else while the thread is working !!!
      }
      
      private void SimpleDoWorkMethod(object s) {
          // Do some work here...
      }
      

      第四,将委托视为一个事件,因为事件是基于委托的。事实上,您提供了一个方法来处理像 Button_Click() 这样的事件。要将您的 btnProcess.Click 事件与您的 btnProcess_Click() 方法以编程方式关联,您需要编写:

      btnProcess.Click += new EventHandler(btnProcess_Click);
      

      您在这里所做的是让 btnProcess.Click 事件引用您的 btnProcess_Click() 方法。请注意带有 ThreadStart 委托的 EventHandler 委托。它们的用途完全相同,但用于两种不同的现实(GUI 事件响应和多线程)。

      第五,不要忘记在访问变量之前锁定一个变量,而另一个变量可能想要同时访问它,然后抛出一个跨线程左右的异常,这个,即使对于原始类型,但更具体的是集合,因为它们不是线程安全的。

      希望这会有所帮助! =)

      【讨论】:

      • IMO“除非绝对必要,否则不要做多线程”是过去的观点。使用多核系统当然是必要的,同样需要在面对冗长或潜在的阻塞操作时制作用户友好的应用程序,这根本不应该在 UI 线程中完成。但幸运的是,诸如任务并行库之类的新开发提供了更好的抽象,并使应用程序中的并发性变得更加容易。
      • 是的,确实,例如 .NET 4.0 中的 PLINQ 将非常适合使用。尽管如此,这并不是过去的感觉,而是更像是使用多线程的必要性。大多数开发的软件都实现了一个简单的过程,特别是在管理软件中。如果我们谈论的是工业流程系统中的完全事务性消息传递系统,那将是不同的!不,我的意思是在不需要时不要使用它。不要过度使用线程。 (待续……)
      • 一旦您的应用程序或您的应用程序的迭代交付给您的客户,并且应该更正精确任务的明显性能不足,只有这样您才应该使用多线程来分割一个或多个过程所需的时间。这更有可能称为微调应用程序。但在微调之前,需要知道他的工作是否有效。一旦它工作,然后优化性能。
      猜你喜欢
      • 2011-04-09
      • 1970-01-01
      • 2016-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多