在浏览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<int> 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
}
我希望得到一些指导,如果我以正确的方式接近这一点,以及对我做错的任何见解。
答案 0 :(得分:24)
你肯定错误地实现了它。您将返回Task<int>
,但只有一旦完成所有工作。
在我看来,你应该只有一个同步方法:
private static void MyFunction()
{
// Loop in here
}
然后像这样开始一个任务:
Task task = Task.Run((Action) MyFunction);
如果你愿意,你可以等待那个任务 - 尽管在你给出的例子中,这样做没有意义,因为你在await
之后没有做任何事情。
我也同意里德的看法,使用CancellationToken
会比其他地方的静态旗更干净。
答案 1 :(得分:7)
你确实误解了。
public static Task<int> 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.
}
答案 2 :(得分:3)
您应该考虑使用框架中内置的managed cancellation framework,而不是尝试使用bool
。
基本上,您需要构建CancellationTokenSource
,并将CancellationToken
传递给您的方法,该方法可用于处理取消。
最后,您当前的方法永远不会脱离UI线程。如果您不想阻止UI,则需要使用Task.Run
或类似方法将方法移动到ThreadPool。
答案 3 :(得分:1)
作为替代方案,您可以考虑使用BackgroundWorker类来完成工作,您的UI将保持互动。