Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call back to main thread from a Task

As i don' know about threads much i have a question. I wanna do something in background and in background method i wanna switch back to the main thread on certain condition otherwise work in background. How can i achieve this functionality? I am using a call to StartSyncThread from UI class(c#)

async void StartSyncThread()
{
    await DoSyncAsync();
}

Task DoSyncAsync()
{
    return Task.Run(() => DoSync());            
}

in DoSync method i wanna switch back to main thread so that i can change UI. Please give me a simple solution to do this. Thanks in advance!

like image 866
Jatin Avatar asked May 25 '13 09:05

Jatin


People also ask

What is the difference between a thread and a task?

Differences Between Task And ThreadThe Thread class is used for creating and manipulating a thread in Windows. A Task represents some asynchronous operation and is part of the Task Parallel Library, a set of APIs for running tasks asynchronously and in parallel. The task can return a result.

What is main thread in iOS?

A thread is a sequence of instructions that can be executed by a runtime. Each process has at least one thread. In iOS, the primary thread on which the process is started is commonly referred to as the main thread. This is the thread in which all UI elements are created and managed.


2 Answers

First start your async process, then call Dispatcher.BeginInvoke to get back on the UI thread.

Task.StartNew(() =>
{
   // Do Something Async

   Dispatcher.BeginInvoke(() =>
   {
      // Update Your UI Here 
   });
});

Note that Dispatcher is not a static - this relies on your code being a part of a member function for a UI object, like a method on your page object.

like image 180
Deeko Avatar answered Sep 28 '22 20:09

Deeko


There are a couple of approaches.

The first is to split up the synchronous method into different parts. This is best if your synchronous method calculates different types of things that go into different parts of the UI:

async Task DoSyncAsync()
{
  myDataBoundUIProperty1 = await Task.Run(() => DoSync1());
  myDataBoundUIProperty2 = await Task.Run(() => DoSync2());
}

The second is to use progress reporting. This is best if your UI updates are all of the same type:

Task DoSyncAsync()
{
  Progress<MyProgressType> progress = new Progress<MyProgressType>(progressUpdate =>
  {
    myDataBoundUIProperty = progressUpdate;
  });
  return Task.Run(() => DoSync(progress));
}
void DoSync(IProgress<MyProgressType> progress)
{
  ...
  if (progress != null)
    progress.Report(new MyProgressType(...));
  ...
}

There is a final alternative, but I strongly recommend one of the two above. The two solutions above will result in a better code design (separation of concerns). The third alternative is to pass in a TaskFactory that can be used to run arbitrary code on the UI context:

Task DoSyncAsync()
{
  var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
  var factory = new TaskFactory(scheduler);
  return Task.Run(() => DoSync(factory));
}
void DoSync(TaskFactory factory)
{
  ...
  scheduler.StartNew(() => { ... });
  ...
}

Again, I don't advise this last solution since it conflates your UI update logic with your background task logic. But it's better than using Dispatcher or Control directly.

like image 26
Stephen Cleary Avatar answered Sep 28 '22 19:09

Stephen Cleary