我们正在开发一个Windows应用程序,它可以满足工程计算的需要。因此,我们基本上试图将计算模块保持独立并在单独的工作线程中工作,并在方法签名中传递一个Action委托,该委托将被调用以报告UI中的计算进度。在UI中声明的委托处理程序将更新UI。我们发现,虽然计算中正在运行一个巨大的循环,但UI不会显示定期进度并且只显示最终结果。如果在计算循环中引入了1毫秒的线程休眠,则UI将正确更新。这不是预期的行为,因为我们使用单独的Task执行计算并使用BeginInvoke调用更新UI。
我创建了一个简单的应用程序来演示我们的方法和代码,以便更容易理解。显而易见的是,我们遗漏了一些非常简单的东西,但却无法确定它。将欣赏任何见解。
感谢阅读。
private void cmdStart_Click(object sender, EventArgs e)
{
txtResultDIsplay.Text = "";
var maxIterations = long.Parse(txtIterationNo.Text.Trim());
var ui = TaskScheduler.FromCurrentSynchronizationContext();
Task<double> calculationTask = Task.Factory.StartNew<double>(() => SumRootN(maxIterations, UpdateProgress));
var handleResultTask = calculationTask.ContinueWith((t) => DisplayResult(t),
CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, ui);
}
private void DisplayResult(Task<double> calculationTask)
{
txtResultDIsplay.Text = "Final Calculation Result : " + calculationTask.Result.ToString();
}
private void UpdateProgress(string msg)
{
this.BeginInvoke((MethodInvoker)delegate
{
txtResultDIsplay.Text = msg;
});
}
public double SumRootN(long maxIterations, Action<string> progressUpdateDelegate)
{
int root = 20;
double result = 0;
for (long i = 1; i < maxIterations; i++)
{
Thread.Sleep(1);
result += Math.Exp(Math.Log(i) / root);
progressUpdateDelegate(result.ToString("0.00000"));
}
return result;
}
答案 0 :(得分:0)
您可能会在进度更新中充斥UI线程。您需要找到一种方法来防止发生大量更新。
我们可以使用任务解决问题!
Task progressTask = null;
private void UpdateProgress(string msg)
{
//only schedule work if the task if not running
if(progressTask == null || progressTask.IsCompleted) //updates will end if there is an exception!
{
//Create a task representing the update
progressTask = Task.Factory.FromAsync<object>(BeginInvoke(new Action(() => txtResultDIsplay.Text = msg)), this.EndInvoke)
.ContinueWith(() => System.Threading.Thread.Sleep(100)); //add a sleep on the end
}
}
请注意,锁定不会在此处执行,因为如果已经发生更新,您可以跳过更新。