如何将例程拆分为线程? [复制]

Posted

技术标签:

【中文标题】如何将例程拆分为线程? [复制]【英文标题】:How do I split a routine into threads? [duplicate] 【发布时间】:2012-03-15 09:57:28 【问题描述】:

可能重复:Timing issue - DGV refreshes before process amends the data

我有以下代码

private void btRunReport_Click(object sender, EventArgs e) 

    Process p = new Process(); 
    p.StartInfo.FileName = @"\\fileserve\department$\ReportScheduler_v3.exe"; 
    p.StartInfo.Arguments = "12"; 
    p.Start(); 
    p.WaitForExit(); 
    InitializeGridView(); 
 

p 将更新数据库表 X。 InitializeGridView 更新反映表 X 的 DGV。

问题是如果 p 需要 10 分钟来运行,那么 winForm 在它到达 InitializeGridView() 之前就被冻结了。我需要帮助的是如何让表单在一个单独的线程中启动进程,该线程在幕后工作并运行 InitializeGridView()?

【问题讨论】:

您不能在这样的线程中启动进程,即从前到后,并且触发线程以启动进程将毫无意义。如果您没有 p.WairForExit 您的代码将继续到 InitializeGridView();马上。 简而言之,阅读 C# 4.0 中的Threading in C# - 您尝试做的事情主要是相当容易的。 编辑:错过了您尝试运行 exe 的事实,无论哪种方式,它都是一篇好文章 我认为实现这一点并促进安全取消的唯一方法是使用单独的 AppDomain... 恕我直言,不是重复,而是后续问题。 @till - 同意 - 前一个线程已经结束,这个问题值得单独讨论。虽然我想我可能在上一篇文章的 cmets 中问过这个问题(我会删除它) 【参考方案1】:

如果您需要在进程完成后运行 InitialilzeGridView() 方法:

    Dispatcher.CurrentDispatcher 设为_currentDispatcher。 在一个单独的线程中启动进程,并在其中使用WaitForExit()。 让线程通过_currentDispatcher.BeginInvoke 调用您的InitializeGridview() 方法。

这里有一些代码可以帮助您:

注意:您需要通过项目的“添加引用”对话框添加对 WindowsBase 的引用。

using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Threading;

private readonly Dispatcher _currentDispatcher = Dispatcher.CurrentDispatcher;
private delegate void ReportingSchedulerFinishedDelegate();

private void btRunReport_Click(object sender, EventArgs e)

    btRunReport.Enabled = false;
    btRunReport.Text = "Processing..";
    var thread = new Thread(RunReportScheduler);
    thread.Start();


private void InitializeGridView()

    // Whatever you need to do here


private void RunReportScheduler()

    Process p = new Process();
    p.StartInfo.FileName = @"\\fileserve\department$\ReportScheduler_v3.exe";
    p.StartInfo.Arguments = "12";
    p.Start();
    p.WaitForExit();
    _currentDispatcher.BeginInvoke(new ReportingSchedulerFinishedDelegate(ReportingSchedulerFinished), DispatcherPriority.Normal);


private void ReportingSchedulerFinished()

    InitializeGridView();
    btRunReport.Enabled = true;
    btRunReport.Text = "Start";

【讨论】:

直到 - 您的解决方案似乎完美运行 - 我只需要研究它以了解它现在是如何工作的! 这很简单:在自己的线程中运行长时间运行的 RunReportSchedule。后台线程的问题是您可能无法直接访问由主 GUI 线程处理的元素。 _currentDispatcher 将保存来自您的 GUI 线程的调度程序的引用,并且您可以在完成数据准备后通过委托传递指令以运行 ReportSchedulerFinished。

以上是关于如何将例程拆分为线程? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

29多线程(线程池定时器)将一个文件复制多次拆分文件并合并多线程复制文件

29多线程(线程池定时器)将一个文件复制多次拆分文件并合并多线程复制文件

WatcherThread如何调用JVM监视例程?

线程题--拆分文件

循环中的线程池队列用户工作项 |拆分为子线程

进程线程协程例程过程的区别是什么?