如何在C#中处理这种异步编程方案

时间:2013-03-12 13:00:39

标签: c# asp.net .net c#-4.0 asynchronous

我在5分钟后接受采访。我得到了这个场景,他问我如何在C#1.0或2.0中处理这个问题。他说有一个基本功能可以解决这个问题,我不确定。有人可以帮忙:(

问题:

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

我给的答案:

我告诉多线程并说关于异步和等待。他期待在C#2.0中处理这个问题的简单方法。我猜测异步委托。他不相信。请有人用简单易懂的代码解释我:)

2 个答案:

答案 0 :(得分:2)

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

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()
{

}

答案 1 :(得分: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();