创建复杂功能的响应版本

pat*_*ryk 3 c# wpf multithreading asynchronous

我正在做一个小项目.我需要实现某种算法,在大多数情况下会占用大量的CPU资源,因此需要一些时间来执行和返回.我希望这种方法能够响应并通知任何进展.我可能还想在进行这些计算时执行其他一些过程.

考虑这个具有复杂方法的类

class Engine
{
    public int ComplexMethod(int arg)
    {
        int result = 0;

        for (int i = 0; i < 100000; i++)
        {
            for (int j = 0; j < 10000; j++)
            {
                // some complex and time-consuming computations
            }

            // it would be nice to get notified on arriving this point for example
        }

        return result; 
    }
}
Run Code Online (Sandbox Code Playgroud)

这种情况的最佳方法是什么?

编辑:我应该提到它是一个带有UI(WPF应用程序)的应用程序.

Tho*_*que 8

您可以使用新的线程运行该进程Task.Run,并使用该IProgress<T>接口来通知进度:

class Engine
{
    public int ComplexMethod(int arg, IProgress<double> progress)
    {
        int result = 0;

        for (int i = 0; i < 100000; i++)
        {
            for (int j = 0; j < 10000; j++)
            {
                // some complex and time-consuming computations
            }

            progress.Report(i / 100000);
        }

        return result; 
    }
}

...

var progress = new Progress<double>(p => ShowProgress(p));
var result = await Task.Run(() => engine.ComplexMethod(arg, progress));
ShowResult(result);
Run Code Online (Sandbox Code Playgroud)

如果您有UI(很可能),则会在UI线程上使用Control.Invoke(Windows窗体)或Dispatcher.Invoke(WPF,WinRT,Silverlight)自动调用progress委托,前提是该Progress<T>实例是在UI线程上创建的.

请注意,async/await如果计算受CPU限制,则无法帮助(在方法内部).但是,它可以用来更容易检索结果,如上所示.如果由于某种原因,你不能或不想使用await,可以使用ContinueWith,指定TaskScheduler.FromCurrentSynchronizationContextscheduler参数.