1

5分钟前我刚面试。我遇到了这种情况,他问我如何在 C# 1.0 或 2.0 中处理这个问题。他说有一个基本功能可以处理这个问题,我不确定。有人可以帮忙吗:(

问题:

Winform 应用程序中有 2 个文本框和一个按钮。一个文本框接受输入值,当单击按钮时,它会在服务器中处理输入,这会花费大量时间,最后会在另一个文本框中显示结果。由于服务器需要很长时间,UI不应该被打断,你如何处理他问我的这种情况:(

我给的答案:

我告诉了多线程并谈到了异步和等待。他期待在 C# 2.0 中有一种简单的方法来处理这个问题。我在猜测异步委托。他不相信。请有人用几乎可以理解的代码解释我:)

4

2 回答 2

2

您将在 UI 的单独线程中运行长时间运行的进程以防止它挂起,BackgroundWorker例如可能会使用 a:-

bgWorker.RunWorkerAsync([DATA TO PROCESS])//Passing in data to operate on

private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
      MyObject obj = (MyObject)sender;

      //
      // Do some work with the data on the server
      // 

      // Report on progess, is it done?
      bgWorker.ReportProgress();
}

你也可以有一个工作完成方法

 private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
 {
       //Work is complete, notify user
 }

您也可以使用ThreadPool,这需要更多设置,但我发现它更灵活。例如: -

ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), [DATA TO PROCESS]);
Interlocked.Increment(ref workItems);

workItems 将是剩余要处理的项目数的计数,这可用于跟踪任务是否完成。然后我们定义一个DoWork方法来处理数据并减少我们的 workItems 计数器。处理完项目后,我们会通过代表报告进度,例如:-

  private delegate void ThreadDone(MyObject obj);
  private delegate void TaskDone();

  public void DoWork(object sender)
   {
        MyObject obj = (MyObject)sender;

        this.Invoke(new ThreadDone(ReportProgress), result);
        Interlocked.Decrement(ref workItems);

        if (workItems == 0)
        {
            this.Invoke(new TaskDone(WorkComplete));
        }
    }

报告进度可能如下所示:-

private void ReportProgress(MyObject obj)
{
    if (workItems >= 0)
    {
        //Job isn't complete, report progress             
    }
}

private void WorkComplete()
{

}
于 2013-03-12T13:07:20.863 回答
0

在 .Net 2 winform 应用程序中,最简单的解决方案是使用BackgroundWorker。它的事件在 UI 线程上引发,因此您不需要自己进行任何编组。

通常的模式如下所示:

BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += delegate(object sender, DoWorkEventArgs e) {
    try {
        e.Result = server.LongRunningOperation();
    }
    catch(Exception ex) {
        e.Error = ex;
    }
};

bg.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e) {
    //update UI
};

bg.RunWorkerAsync();
于 2013-03-12T13:06:47.617 回答