创建复杂功能的响应版本

时间:2014-01-06 18:43:10

标签: 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; 
    }
}

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

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

2 个答案:

答案 0 :(得分: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);

如果您有UI(很可能),将使用Control.Invoke(Windows窗体)或Dispatcher.Invoke(WPF,WinRT,Silverlight)在UI线程上自动调用渐进委托,只要在UI线程上创建了Progress<T>实例。

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

答案 1 :(得分:0)

假设您使用的是.NET 4.5(C#5),则可以使用TPLhttp://msdn.microsoft.com/en-us/library/dd997423(v=vs.110).aspx)。

由于不了解您的算法,我所能建议的是您返回Task<int>而不是返回int。这将允许该功能与其他任务并行运行。

我会推荐以下内容:

public Task<int> ComplexMethodAsync(int arg)
{
  Task.Run(()=>ComplextMethod(arg));
}

现在,当您运行此方法时,ComplexMethod(arg)将在ThreadPool的单独线程上调用。称之为:

await ComplextMethodAsync(xyz);

查看async/await了解详情。