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

Kar*_*y S 19 c# wpf multithreading asynchronous

在浏览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
}
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*eet 26

你肯定错误地实现了它.你回来了Task<int>,但只有一次完成所有的工作.

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

private static void MyFunction()
{
    // Loop in here
}
Run Code Online (Sandbox Code Playgroud)

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

Task task = Task.Run((Action) MyFunction);
Run Code Online (Sandbox Code Playgroud)

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

我也同意里德的看法,CancellationToken在其他地方使用a 比使用静态标志更清洁.


Sco*_*ain 8

你确实误解了.

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
}
Run Code Online (Sandbox Code Playgroud)

所有这些代码仍然发生在初始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.
}
Run Code Online (Sandbox Code Playgroud)