Reputation: 1907
I'm currently trying to show a dialog while an asynchronous action is performed.
My architecture was event-based before as I want that the user can easily implement custom graphic user interfaces.
Now I'm heading for other ways, in my case return types for synchronous methods instead of EventArgs containing the data and then async-await + tasks.
Example:
public bool SearchForUpdates()
{
// ...
return true;
}
Now my async method should look like that:
public async Task<bool> SearchForUpdatesAsync()
{
return await Task.Factory.StartNew(() => SearchForUpdates());
}
These methods are defined in a Manager-class. First: Is it right that the async method awaits the synchronous one or should the synchronous one await the asynchronous one?
Then there is another class that is the interface between the Manager-class and the UI. While there is a search for updates the relating dialog should be shown:
public async void ShowUserInterface()
{
var searchDialog = new SearchDialog();
Task<bool> searchTask = _manager.SearchForUpdatesAsync();
IAsyncResult result = searchDialog.BeginInvoke(new Action(() => seachDialog.ShowDialog()));
bool updatesFound = await searchTask;
if (((DialogResult)searchDialog.EndInvoke(result)) == DialogResult.Cancel)
{
// Cancelled, do stuff
}
searchDialog.Close();
}
That is what I thought, so there would be a way to call that and show a custom UI. Logical problem: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
My plan seems to fail, is it maybe completely wrong? Or is there a way to show the dialog like that? There should be a way to make ShowDialog non-blocking so that I can continue and await the call. So I am actually searching for a way to call BeginInvoke, but I don't know where, something like Application.Current.Dispatcher.Invoke in WPF maybe, I don't know.
Thanks!
Upvotes: 2
Views: 4105
Reputation: 942368
As discussed in the comments, you are simply using the wrong Control reference to call BeginInvoke() on. The dialog cannot work, it wasn't created yet. Which is important, .NET cannot figure out what thread owns the window until the window is committed to a specific thread. Which doesn't happen until you call Show().
But any other window will do, you must already have one since it isn't legal or practical to display a dialog without an owner. You must provide a constructor or a property so the client code can provide a reference to such a window. Any will do, the main window of the app is a practical choice.
You can completely separate a class from the UI implementation (not practical here since you display a dialog) by copying the value of Synchronization.Current in the constructor. On which you later can call its Post() method. All UI class libraries in .NET install a synchronization provider that will marshal the call.
Upvotes: 1