Reputation: 803
I have a method which I call in a new task with
// get the dispatcher for the UI thread
var uiDispatcher = Dispatcher.CurrentDispatcher;
Task.Factory.StartNew(() => BackgroundThreadProc(uiDispatcher));
In the method BackgroundThreadProc()
I need a delay of few seconds. I tried it with the DispatcherTimer and the task.delay function but it didn't work. The only thing which worked was the System.Threading.Thread.Sleep(1)
but I think the Thread.Sleep()
function isn't the best solution.
This is my function:
public void BackgroundThreadProc(Dispatcher uiDispatcher)
{
for (var i = 0; i < 100; i++)
{
var task = Task.Delay(1000).ContinueWith(t =>
{
// create object
var animal = new Animal { Name = "test" + i };
uiDispatcher.Invoke(new Action(() => log(animal)));
});
}
}
As I found out it didn't work because the DispatcherTimer is running in the UI thread. How I can accomplish the delay in the function which is in a other thread than the UI thread?
Update:
Now I tried it with the timer:
public void BackgroundThreadProc(Dispatcher uiDispatcher)
{
for (var i = 0; i < 100; i++)
{
var _delayTimer = new System.Timers.Timer();
_delayTimer.Interval = 1000;
//_delayTimer.Enabled = true;
_delayTimer.Elapsed += delegate
{
var animal = new Animal { Name = "test" + i };
uiDispatcher.Invoke(new Action(() => log(animal)));
_delayTimer.Stop();
};
_delayTimer.Start();
}
}
Upvotes: 1
Views: 4647
Reputation: 61656
Are you limited to C# 4.0? I assume you're not, because Task.Delay
wouldn't be available.
So, make BackgroundThreadProc
an async
method and use await
inside it:
// get the dispatcher for the UI thread
var uiDispatcher = Dispatcher.CurrentDispatcher;
var task = BackgroundThreadProc(uiDispatcher));
// ...
public async Task BackgroundThreadProc(Dispatcher uiDispatcher)
{
for (var i = 0; i < 100; i++)
{
await Task.Delay(1000).ConfigureAwait(false);
// create object
var animal = new Animal { Name = "test" + i };
uiDispatcher.Invoke(new Action(() => log(animal)));
}
}
You really don't need Task.Factory.StartNew
here, the execution will continue on thread pool after await Task.Delay
.
Apparently, you're only updating the UI from this BackgroundThreadProc
. If that's the case, just remove ConfigureAwait(false)
and don't use uiDispatcher.Invoke
:
public async Task BackgroundThreadProc()
{
for (var i = 0; i < 100; i++)
{
await Task.Delay(1000);
// create object
var animal = new Animal { Name = "test" + i };
log(animal);
}
}
This loop will be executing asynchronously on the WPF UI thread.
Otherwise, if you do have any other CPU-bound work before Task.Delay
, then you may need Task.Factory.StartNew
to avoid freezing the UI (note Unwrap
):
var task = Task.Factory.StartNew(() =>
BackgroundThreadProc(uiDispatcher)).Unwrap();
You can also use Task.Run
, which unwraps the inner task automatically:
var task = Task.Run(() => BackgroundThreadProc(uiDispatcher));
Upvotes: 1
Reputation: 203802
Use Task.Delay
to introduce a delay asynchrnoously:
var task = Task.Delay(1000)
.ContinueWith(t => BackgroundThreadProc());
Upvotes: 4