2

I have started using Task Parallel Library (TPL) in my C++/CLI project. This works well when running simple tasks which can be run independently. The software that I'm writing has the ability to check for updates on a server. This was previously done on the main thread of the but this made the GUI freeze for the duration of the check which really doesn't give a good impression of the software for the user.

I have therefore tested with using TPL to run the check. I can start the check for updates (following the directions from Using .NET (3.5) Task Parallel Library in C++/ CLI) like this:

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 has the nice feature of making it possible to define the order of tasks using Task.ContinueWith(...) as outlined in Task chaining (wait for the previous task to completed). What I want to do is (in C#):

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

Where OnVersionCheckDone(bool) can take care of asking the user how to proceed if there is indeed a new version available. All examples for how to do this are written in C# and I have not been able to convert this into C++/CLI.

Is this at all possible ?

Community
  • 1
  • 1
  • 3
    Starting a task and waiting on it is pointless, you might as well run the code on the same thread. That C++/CLI doesn't support lambdas is pretty painful if you want to use Task, it is however something you'll have to deal with. You'll get lots of tiny private helper functions. Never overlook the option to write this code in C#, language interop is a strong .NET feature. – Hans Passant Nov 12 '14 at 11:11
  • I agree that there's no point in just waiting for the task. What I was looking for was a way to work around the missing support for lambdas. – Mattias Johansson Nov 12 '14 at 12:54
  • For what it's worth, I was surprised to learn from Hans's comment that C++/CLI doesn't support managed lambdas. In doing some research to learn more about why this is, what the future might hold, and what the alternatives are, I came across a couple of pages I found particularly useful (including a SO answer from Hans four years ago): http://stackoverflow.com/questions/2777445/lambda-expressions-as-clr-net-delegates-event-handlers-in-visual-c-2010 and http://www.codeproject.com/Articles/277612/Using-lambdas-Cplusplus-vs-Csharp-vs-Cplusplus-CX – Peter Duniho Nov 13 '14 at 02:50

1 Answers1

2

While C++ does not support managed lambdas, you can do a little fanagling to get delegates to work, and cover your own variables when necessary. In this case, the ContinueWith delegate takes a Task as an argument, so we don't have to do too much.

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();
}
Brain2000
  • 4,655
  • 2
  • 27
  • 35