我有一个WPF GUI,我想在其中按一个按钮来启动一个长任务,而不会在任务持续时间内冻结窗口。当任务正在运行时,我希望获得进度报告,并且我希望加入另一个按钮,该按钮将在我选择的任何时间停止任务。
我想不出使用async/await/task的正确方法。我不能包括我尝试过的所有东西,但这就是我目前所拥有的。
WPF窗口类:
public partial class MainWindow : Window
{
readonly otherClass _burnBabyBurn = new OtherClass();
internal bool StopWorking = false;
//A button method to start the long running method
private async void Button_Click_3(object sender, RoutedEventArgs e)
{
Task slowBurn = _burnBabyBurn.ExecuteLongProcedureAsync(this, intParam1, intParam2, intParam3);
await slowBurn;
}
//A button Method to interrupt and stop the long running method
private void StopButton_Click(object sender, RoutedEventArgs e)
{
StopWorking = true;
}
//A method to allow the worker method to call back and update the gui
internal void UpdateWindow(string message)
{
TextBox1.Text = message;
}
}
还有一个用于worker方法的类:
class OtherClass
{
internal Task ExecuteLongProcedureAsync(MainWindow gui, int param1, int param2, int param3)
{
var tcs = new TaskCompletionSource<int>();
//Start doing work
gui.UpdateWindow("Work Started");
While(stillWorking)
{
//Mid procedure progress report
gui.UpdateWindow("Bath water n% thrown out");
if (gui.StopTraining) return tcs.Task;
}
//Exit message
gui.UpdateWindow("Done and Done");
return tcs.Task;
}
}
这会运行,但WPF函数窗口在worker方法启动后仍会被阻塞。
我需要知道如何安排async/await/task声明以允许
A)不阻塞gui窗口的worker方法。
B)让worker方法更新gui窗口。
C)允许gui窗口停止中断并停止工作方法
任何帮助或指点都是非常感谢的。
发布于 2014-11-24 03:50:35
您对TaskCompletionSource<T>
的使用不正确。TaskCompletionSource<T>
是一种为异步操作创建TAP-compatible wrappers的方法。在您的ExecuteLongProcedureAsync
方法中,示例代码都是受CPU限制的(即,本质上是同步的,而不是异步的)。
因此,将ExecuteLongProcedure
编写为同步方法要自然得多。对标准行为使用标准类型也是一个好主意,特别是using IProgress
for progress updates和CancellationToken
for cancellation
internal void ExecuteLongProcedure(int param1, int param2, int param3,
CancellationToken cancellationToken, IProgress<string> progress)
{
//Start doing work
if (progress != null)
progress.Report("Work Started");
while (true)
{
//Mid procedure progress report
if (progress != null)
progress.Report("Bath water n% thrown out");
cancellationToken.ThrowIfCancellationRequested();
}
//Exit message
if (progress != null)
progress.Report("Done and Done");
}
现在,您有了一个使用适当约定的更可重用的类型(没有GUI依赖项)。它可以这样使用:
public partial class MainWindow : Window
{
readonly otherClass _burnBabyBurn = new OtherClass();
CancellationTokenSource _stopWorkingCts = new CancellationTokenSource();
//A button method to start the long running method
private async void Button_Click_3(object sender, RoutedEventArgs e)
{
var progress = new Progress<string>(data => UpdateWindow(data));
try
{
await Task.Run(() => _burnBabyBurn.ExecuteLongProcedure(intParam1, intParam2, intParam3,
_stopWorkingCts.Token, progress));
}
catch (OperationCanceledException)
{
// TODO: update the GUI to indicate the method was canceled.
}
}
//A button Method to interrupt and stop the long running method
private void StopButton_Click(object sender, RoutedEventArgs e)
{
_stopWorkingCts.Cancel();
}
//A method to allow the worker method to call back and update the gui
void UpdateWindow(string message)
{
TextBox1.Text = message;
}
}
https://stackoverflow.com/questions/27089263
复制相似问题