4

I want to mimic the behavior of objective-c dispatch queues in c#. I see that there is a task parallel library but I really don't understand how to use it and was hoping to get some explanation on how.

In objective c i would do something like:

-(void)doSomeLongRunningWorkAsync:(a_completion_handler_block)completion_handler
{
 dispatch_async(my_queue, ^{
   result *result_from_long_running_work = long_running_work();
   completion_handler(result_from long_running_work);
 });
}

-(void)aMethod
{
  [self doSomeLongRunningWorkAsync:^(result *) { // the completion handler
    do_something_with_result_from_long_running_async_method_above;
  }];

}

How is this translated into c# style task parallel library?

Any comparison sites?

Avba
  • 14,822
  • 20
  • 92
  • 192
  • 1
    For those of us who don't know Objective C or its libraries, could you explain what is it that you actually want? Also, can you use C# 5.0? – svick Jun 23 '13 at 13:03
  • 1
    i can use c# 5 . Essentially in objective - c you create code blocks (the stuff in the curly brackets) and you send those as expressions (sort of like a function pointer - in the block is the code to execute) to a "dispatch queue" - dispatch queues act as the abstraction to the different background threads managed by the framework. The queues send the blocks and return immediatly and the blocks are guaranteed to run FIFO in the order they were sent to the queue. If you want to get a value back from a block - you supply a callback (the "result" type in the function) – Avba Jun 23 '13 at 13:21
  • That sounds quite close to what `async`-`await` does in C# 5.0 (except that you don't need callbacks). I suggest that you read up about that and come back if you have some specific question. – svick Jun 23 '13 at 13:50
  • I've read the documentation and it seems complicated. My question in short is how do I create a method with returns a task such that my task can be run asynchronously. – Avba Jun 23 '13 at 14:16

1 Answers1

1

If all you want is to execute some long-running CPU-intensive code on a background thread, and when it's done, process the result on the UI thread, use Task.Run() in combination with await:

async Task AMethod()
{
    var result = await Task.Run(() => LongRunningWork());
    DoSomethingWithResult(result);
}

The AMethod() is now an async Task method, which means its caller also has to be an async method.

svick
  • 236,525
  • 50
  • 385
  • 514
  • Is there any way to do this in-line, ie with `Func<>` or `Action<>` ? I mean -- do I need to create a whole new function, or can I declare a `Func<>` or `Action<>` as `async`? – damian Nov 20 '14 at 16:45
  • @damian You can have async `Func`, e.g. the one above would be something like `Func aMethod = async () => { … };`. But you shouldn't use `async` `Action`s, that's the same as `async void` methods, and those are a bad idea. – svick Nov 20 '14 at 17:51
  • Is there any way to achieve this in reverse: Dispatch to main thread from background thread? – helmesjo Apr 01 '15 at 10:48
  • @helmesjo Usually, if you need to do that, it means your code is not well structured. But if you actually want to do it, you need to use a UI framework-specific method, like `Dispatcher.Invoke()` for WPF or `Control.Invoke()` for WinForms. – svick Apr 01 '15 at 10:53
  • 1
    @svick How come? If I, say, run a serializer on a background thread, but want to guarantee that the ISerializeCallback-methods (before serialize etc.) are invoked on the main thread, this sounds perfectly fine... (though waiting for main thread to finish would be required here of course). – helmesjo Apr 01 '15 at 12:39
  • @helmesjo I don't know the specifics of that, but serialization sounds exactly like something that *shouldn't* interact with the UI (which is why you usually need to run on the UI thread). – svick Apr 01 '15 at 13:07
  • @svick I'm not saying the serialisation per say is running on the main thread, but it could definitely be a guarantee by the API. Anyways, I'm in Unity, which (as anyone using it might know) sets lots of restrictions on whatever you try to do. So yes, I'm in a special case here. – helmesjo Apr 01 '15 at 13:44
  • this answer is not correct because tpl doesn't guarantee to run FIFO – Alexander Danilov Jul 21 '16 at 11:50
  • To call the method in this answer, doesn't the calling method also need to be async? Compare that to Objective-C / Swift making an async call in response to a user tapping a button and updating the UI on completion with a closure callback. How would that be done in C#? – Aaron Bratcher Nov 14 '16 at 14:00
  • This solution help to solve al the problems related with (You don’t have permission to save the file “CallDirectory” in the folder “Library") in background fetch when you call a service. – Marcos José Pérez Pérez Sep 25 '17 at 21:16