C#Threading / Async:在UI可交互的情况下在后台运行任务

在浏览Async / Await和Threading之后,我仍然不确定将它应用于我的情况的正确方法。 无论我尝试我的UI的变化仍然挂起,因为我似乎不是异步调用我想要的函数,另外,我可能实际上需要线程为我的解决方案。

我正在尝试做的事情:我有一个WPF应用程序,其中有一个按钮,我想开始一个操作,仍然允许通过UI或其他方式与程序交互。 一旦满足在此函数之外确定的条件,该函数应该结束。 对我来说,这听起来相当标准,但我有一种感觉,我误解了一些东西,我已经错误地实现了它。

我现在拥有的:

private async void start_button_Click(object sender, RoutedEventArgs e) { await StaticClass.MyFunction(); } private void stop_button_Click(object sender, RoutedEventArgs e) { StaticClass.stopFlag = true; } public static Task myFunction() { //Stuff Happens while(StaticClass.stopFlag == false) //Do Stuff //Stuff Happens return Task.FromResult(1) //I know this is bad, part of the reason I'm asking } 

我希望得到一些指导,如果我正在以正确的方式接近这一点以及对我做错的任何见解。

你肯定错误地实现了它。 您将返回一个Task ,但只有在完成所有工作后才会返回。

在我看来,你应该只有一个同步方法:

 private static void MyFunction() { // Loop in here } 

然后像这样开始一个任务:

 Task task = Task.Run((Action) MyFunction); 

然后,如果你愿意,你可以等待那个任务 – 虽然在你给出的例子中,这样做是没有意义的,因为你无论如何都没有做任何事情。

我也同意里德的观点,使用CancellationToken比其他地方的静态标志更清晰。

你确实误解了。

 public static Task myFunction() { //Stuff Happens while(StaticClass.stopFlag == false) //Do Stuff //Stuff Happens return Task.FromResult(1) //I know this is bad, part of the reason I'm asking } 

所有这些代码仍然发生在初始await StaticClass.MyFunction(); 呼叫,它永远不会将控制权返回给呼叫者。 您需要做的是将循环部分放入单独的线程中。

 public static async Task myFunction() { //Stuff Happens on the original UI thread await Task.Run(() => //This code runs on a new thread, control is returned to the caller on the UI thread. { while(StaticClass.stopFlag == false) //Do Stuff }); //Stuff Happens on the original UI thread after the loop exits. } 

您应该考虑使用框架内置的托管取消框架 ,而不是尝试使用bool

基本上,您将构建一个CancellationTokenSource ,并将CancellationTokenSource传递给您的方法,该方法可用于处理取消。

最后,您当前的方法永远不会脱离UI线程。 如果您不想阻止UI,则需要使用Task.Run或类似方法将方法移动到ThreadPool。

作为替代方案,您可以考虑使用BackgroundWorker类来完成工作,您的UI将保持交互。