-1

我有一个单线程 C# 工具,其中有一堆 UI 输入控件。基于这些控件,以及一些输入的 Excel 文件,正在进行一些处理。此处理需要 10~15 秒,在此期间程序无响应。工作完成后,输出文本会在文本框中提及。

现在我有一个可以完成所有工作的函数。但是,此功能取决于用户提供的 UI 输入。

我只是尝试使用以下代码应用一些线程:

workerThread = new Thread(this.WorkerFunction);
workerThread.Start();
//workerThread.Join();
output.Text = outputStringBuilder.ToString();

我基本上在这里使用相同的 Form 实例,因为使用另一个 Form 实例将不起作用,因为新的 Form 实例不包含用户指定的输入。

正如上面提到的代码,它不起作用。我没有在文本框中看到输出文本。它仅在我启用该workerThread.Join();语句时才有效,但随后我看到了 10~15 秒的延迟,这打破了线程的整个要点..

那么如何在此设置中添加线程,而不必向 workerFunction 添加一大堆输入参数(因为我想查看 UI 控件输入的原样)..?

4

2 回答 2

0

但是,此功能取决于用户提供的 UI 输入。

嗯,这是您需要解决的第一个问题。您需要将 UI 交互与业务逻辑和长期运行的流程分开。

调用长期运行的函数之前,您应该从 UI 中提取执行此处理所需的任何信息。将该信息传递给通过一个或多个参数进行处理的方法。如果有很多信息,则可能值得将其封装在特定的数据持有者类(或类,或集合等,取决于信息的范围)中。

接下来,不是让这个过程用它生成​​的任何结果来更新 UI,而是让这个函数返回一个表示业务操作结果的值;然后,UI 代码可以获取这些结果并根据需要操作 UI。

现在,有许多不同的线程工具专门设计用于帮助您在 UI 程序中执行长时间运行的操作,同时在另一个线程中执行长时间运行的工作,同时在 UI 上下文中执行与 UI 相关的工作。其中之一是BackgroundWorker类。(如果您使用的是 C# 5.0,则可以将任务并行库与asyncandawait关键字结合使用,这确实要好得多。)

完成此操作后,您的代码将很好地融入BackroundWorker.

首先从 UI 中提取数据。然后创建 BGW,分配一个DoWork处理程序来完成工作并使用您从 UI 中提取的信息。将 设置为Result操作的结果。然后使用RunWorkerCompleted处理程序用这些结果更新 UI。

var myUIInfo = new SomeClass(){Info = someControl.Text
    , Other = someOtherControl.Selected};
var worker = new BackgroundWorker();
worker.DoWork += (s,e) => e.Result = LongRunningProcess(myUIInfo);
worker.RunWorkerCompleted += (s, e) += UpdateUIWith(e.Result);
worker.RunWorkerAsync();
于 2013-05-21T16:10:01.340 回答
0

如果您的任务很简单并且只需要几行代码,那么您可以简单地将 output.Text 更新移动到 WorkerFunction,而不是整个 BackgroundWorker 设置。请记住使用 Dispatcher 否则它将无法正常工作,方法如下:

Invoke(new MethodInvoker(
            delegate
            {
                // Update output.Text here
            }
            ));
于 2013-05-21T16:15:25.990 回答