【问题标题】: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 中问过这个问题(我会删除它)

标签: c# winforms multithreading


【解决方案1】:

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

  1. Dispatcher.CurrentDispatcher 设为_currentDispatcher。
  2. 在一个单独的线程中启动进程,并在其中使用WaitForExit()
  3. 让线程通过_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。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 2018-07-23
  • 2013-02-05
  • 2018-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多