I'm working mostly with Windows Phone and I'm trying to create something similar to MessageBox - small window that apperas and waits for user's choice (the Thread that invoked window waits). I found three ways how I can achive this goal:
FIRST - TaskCompletionSource
In this case my Task looks like this:
TaskCompletionSource<bool> taskComplete = new TaskCompletionSource<bool>();
private async Task myTask1()
{
window.Show(); // Show window
await taskComplete.Task;
//some job run after User's choice
MessageBox.Show("Job finished");
}
And my window's Closed event:
private void WindowClosedEvent1(object sender, EventArgs e)
{
taskComplete.SetResult(true);
}
SECOND - SemaphoreSlim
My Task and event:
private SemaphoreSlim mySemaphore = new SemaphoreSlim(0, 1);
private async Task myTask2()
{
window.Show(); // Show window
await mySemaphore.WaitAsync();
//some job run after User's choice
MessageBox.Show("Job finished");
}
private void WindowClosedEvent2(object sender, EventArgs e)
{
mySemaphore.Release();
}
THIRD - EventWaitHandle:
My Task and Event:
EventWaitHandle waitForUser = new EventWaitHandle(false, EventResetMode.AutoReset, "myEventName");
private async Task myTask3()
{
window.Show(); // Show window
await Task.Run(() => waitForUser.WaitOne());
//some job run after User's choice
MessageBox.Show("Job finished");
}
private void WindowClosedEvent3(object sender, EventArgs e)
{
waitForUser.Set();
}
All three methods work, but I cannot decide which to use. I'm mostly thinking that 1) or 2) will be the best choice. Can any of those three methods cause troubles in some circumstances? Has anybody tried something like this?
The variant #1 with
TaskCompletionSource
is enough for this, that's whatTaskCompletionSource
is for. #2 and #3 are unnecessary complex, especially #3 withTask.Run(..)
, which is wasting a pool thread for a blocking wait.Because there is no modality for
Popup
in WP, all three approaches potentially have one major issue: re-entrancy. E.g., ifmyTask2()
is called upon a button click, nothing prevents user from clicking that button again, which would start anothermyTask2()
. The UI workflow of your app should account for this. This is discussed here.