问题
I have a helper method that shows an ContentDialog with an input box that accepts string data. My issue is that it takes about 1 second after OK is clicked before the caller gets the string back (and it's very noticeable). I theorized that maybe it was the dialog fading out default animation/transition to end before the dialog returned.
In the code below, there's about a 1 second delay between when OK is clicked on the dialog and when the "return textBox.Text" fires.
/// <summary>
/// Shows an simple input box to get a string value in return.
/// </summary>
/// <param name="title">The title to show at the top of the dialog.</param>
/// <param name="message">The message shown directly above the input box.</param>
/// <param name="defaultValue">A value to prepopulate in the input box if any.</param>
/// <returns></returns>
public static async Task<string> ShowInput(string message, string defaultValue, string title)
{
var dialog = new ContentDialog
{
Title = title
};
var panel = new StackPanel();
panel.Children.Add(new TextBlock { Text = message, TextWrapping = Windows.UI.Xaml.TextWrapping.Wrap });
var textBox = new TextBox();
textBox.Text = defaultValue;
textBox.SelectAll();
textBox.KeyUp += (o, e) =>
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
dialog.Hide();
}
e.Handled = true;
};
panel.Children.Add(textBox);
dialog.Content = panel;
dialog.PrimaryButtonText = "OK";
await dialog.ShowAsync();
return textBox.Text;
}
My questions are:
Am I missing something I should be setting or is this delay after clicking OK on the ContentDialog out the out of the box behavior?
If it is caused by a transition can I disable it?
- Is there anyway I can speed up the time between when OK is clicked and the await returns?
I am running against 1809 Build 17763.379.
Thank you in advance.
回答1:
As Pratyay mentioned in his comment, the amount of time will vary by device.
But as far as the await
keyword goes, I believe what you are experiencing is intended behavior.
The await operator is applied to a task in an asynchronous method to insert a suspension point in the execution of the method until the awaited task completes. The task represents ongoing work.
Source @ Microsoft Doc
This means that your ShowInput
function will return its Task<string>
object as soon as it reaches the await
keyword. Then after dialog.ShowAsync();
returns it will continue the ShowInput
function asynchronously and place the results into the Task object for you to retrieve.
So although your ShowInput
function should return almost immediately. You will notice a delay between dialog.ShowAsync();
and return textBox.Text;
.
The other thing to keep in mind is that when a window closes, there is usually a bit of processing (disposing of resources, etc.) before the window loop finishes. The way your code is written, you will have to wait until all of that finishes before you get your result.
Is there anyway I can speed up the time between when OK is clicked and the await returns?
I figure the quickest way to get your response back is to not await the ContentDialog, but rather await a signal that occurs right when the content is available.
public static Task<string> ShowInput(string message, string defaultValue, string title)
{
var dialog = new ContentDialog { Title = title };
var panel = new StackPanel();
panel.Children.Add(new TextBlock { Text = message, TextWrapping = Windows.UI.Xaml.TextWrapping.Wrap });
var textBox = new TextBox() { Text = defaultValue };
textBox.SelectAll();
var signal = new TaskCompletionSource<string>();
textBox.KeyUp += (o, e) =>
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
dialog.Hide();
signal.SetResult(textBox.Text);
}
e.Handled = true;
};
dialog.PrimaryButtonClick += (o, e) =>
{
dialog.Hide();
signal.SetResult(textBox.Text);
};
panel.Children.Add(textBox);
dialog.Content = panel;
dialog.PrimaryButtonText = "OK";
dialog.ShowAsync();
return signal.Task;
}
Edit: Doing it this way no longer needs the extra await, as the Task being created has the final result in it.
回答2:
The following solution is not really a performance fix, since there is nothing wrong with the code you have posted.
The basic idea is - since this process takes a while based on the device you can just show a spinner / loading screen just before calling your ShowInput()
method and hiding it after you are done using the value/text that is returned by the ShowInput()
.
For example you can try something like this :
showLoader();
string x = await ShowInput("message","","title");
...
//some more code
...
hideLoader();
Where showLoader/hideLoader will show or hide a lightweight loader screen something like this :
This will make sure user waits until the code has completed execution. (This might be overkill if you are doing something very trivial with the text input)
来源:https://stackoverflow.com/questions/55305898/contentdialog-delay-after-ok-clicked