【问题标题】:Task Parallel Library Task.ContinueWith using C++/CLI任务并行库 Task.ContinueWith 使用 C++/CLI
【发布时间】:2015-01-09 04:23:43
【问题描述】:

我已经开始在我的 C++/CLI 项目中使用任务并行库 (TPL)。这在运行可以独立运行的简单任务时效果很好。我正在编写的软件能够检查服务器上的更新。这以前是在主线程上完成的,但这使得 GUI 在检查期间冻结,这确实不会给用户留下对软件的良好印象。

因此,我使用 TPL 进行了测试以运行检查。我可以像这样开始检查更新(按照Using .NET (3.5) Task Parallel Library in C++/ CLI 的指示):

Void SoftwareUpdateChecker::RunCheck(Boolean automatic)
{
    Task<Boolean>^ versionCheckTask = Task<Boolean>::Factory->StartNew( gcnew Func<Boolean>(this, &SoftwareUpdateChecker::IsUpdateAvailable) );

    // This line is the problem, this freezes the main thread...
    versionCheckTask->Wait();

    Boolean isNewerVersionOnServer = versionCheckTask->Result;

    if(isNewerVersionOnServer)
    {
        QueryUserToDownloadNewVersion();
    }
}

TPL 有一个很好的特性,它可以使用 Task.ContinueWith(...) 定义任务的顺序,如Task chaining (wait for the previous task to completed) 中所述。我想做的是(在 C# 中):

Task.Factory.StartNew( () => IsUpdateAvailable())
   .ContinueWith(() => OnVersionCheckDone(antecendent.Result), 
       TaskScheduler.FromCurrentSynchronizationContext());

如果确实有新版本可用,OnVersionCheckDone(bool) 可以负责询问用户如何继续。如何做到这一点的所有示例都是用 C# 编写的,我无法将其转换为 C++/CLI。

这有可能吗?

【问题讨论】:

  • 启动一个任务并等待它是没有意义的,你还不如在同一个线程上运行代码。如果您想使用 Task,C++/CLI 不支持 lambdas 会非常痛苦,但是您必须处理它。你会得到很多微小的私有辅助函数。永远不要忽视用 C# 编写此代码的选项,语言互操作是一个强大的 .NET 功能。
  • 我同意等待任务没有意义。我一直在寻找一种方法来解决对 lambda 的缺失支持。
  • 对于它的价值,我惊讶地从 Hans 的评论中得知 C++/CLI 不支持托管 lambda。在做一些研究以了解更多关于为什么会这样、未来可能会发生什么以及替代方案是什么时,我发现了几页我发现特别有用的页面(包括四年前 Hans 的 SO 回答):stackoverflow.com/questions/2777445/…codeproject.com/Articles/277612/…

标签: c# .net concurrency c++-cli task-parallel-library


【解决方案1】:

虽然 C++ 不支持托管 lambda,但您可以做一些花哨的工作来让委托工作,并在必要时覆盖您自己的变量。在这种情况下,ContinueWith 委托将 Task 作为参数,因此我们不必做太多。

Void SoftwareUpdateChecker::RunCheck(Boolean automatic)
{
    Task<Boolean>^ versionCheckTask = Task<Boolean>::Factory->StartNew( gcnew Func<Boolean>(this, &SoftwareUpdateChecker::IsUpdateAvailable) );
    versionCheckTask->ContinueWith(gcnew Action<Task<Boolean>^>(this, &SoftwareUpdateChecker::OnVersionCheckDone), TaskScheduler::FromCurrentSynchronizationContext());
}

Void SoftwareUpdateChecker::OnVersionCheckDone(Task<Boolean>^ versionCheckTask)
{
    if(versionCheckTask->Result) QueryUserToDownloadNewVersion();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    相关资源
    最近更新 更多