我在5分钟后接受采访。我得到了这个场景,他问我如何在C#1.0或2.0中处理这个问题。他说有一个基本功能可以解决这个问题,我不确定。有人可以帮忙:(
问题:
Winform应用程序中有2个文本框和一个按钮。一个文本框获取输入值,当单击按钮时,它处理服务器中的输入,这需要花费很多时间,最后将结果显示在另一个文本框中。由于服务器需要很长时间,UI不应该被中断,你如何处理这个他问我的场景:(
我给的答案:
我告诉多线程并说关于异步和等待。他期待在C#2.0中处理这个问题的简单方法。我猜测异步委托。他不相信。请有人用简单易懂的代码解释我:)
答案 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();