了解如何从XDocument.SaveAsync方法获取任务反馈



在我的WPF应用程序中,我使用按钮单击来创建一个XML文件。如果异步任务成功完成,则从中获取反馈并显示消息框。

Window.cs

public partial class BindXml : Window
{
public BindXml()
{
InitializeComponent();
}
private void Create_File_OnClick(object sender, RoutedEventArgs e)
{
XmlCreator xmlCreator = new XmlCreator();
Task task = xmlCreator.CreateXmlAysnc();
MessageBox.Show(task.IsCompletedSuccessfully
? "XML Created Successfully."
: "Wrong");
}

XmlCreator.cs

public async Task CreateXmlAysnc()
{
string filePath =
"E:\OneDrive\Programming\C#\03_Csharp\02_WPF\06_DataBinding\03_Binding\09_BindXml\data.xml";
// Create a xml tree.
XDocument xmlDocument = new XDocument(
new XElement("StudentList",
new XElement("Student",
new XAttribute("Id", "1"),
new XElement("Name", "Tim")),
new XElement("Student",
new XAttribute("Id", "2"),
new XElement("Name", "Gary")),
new XElement("Student",
new XAttribute("Id", "3"),
new XElement("Name", "Tom")))
);
try
{
await using FileStream fileStream = File.Open(filePath, FileMode.Create);
await xmlDocument.SaveAsync(fileStream, SaveOptions.None, CancellationToken.None);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
throw;
}
}

点击按钮后,文件创建成功。然而,消息框显示;错了";。任务未成功完成。然后我使用了下面的代码。消息框将显示为true。

Task task = xmlDocument.SaveAsync(fileStream, SaveOptions.None, CancellationToken.None);
await Task.WhenAll(task);
// Messagebox would show true
MessageBox.Show(task.IsCompletedSuccessfully.ToString());

如果我将Task.Wait()添加到Window.cs中,应用程序就会阻塞。任务似乎从未完成,但文件已创建。

里面的原因是什么?

对于异步和等待模式,惯用方法是await(任务(和catch(异常

因为您来自事件处理程序,所以使用async void来利用异步和等待模式是可以接受的,而不必担心原始任务或更糟的是,尝试使用Wait或任何其他阻塞方法。

此外,当在async方法中产生异常时,它被放置在任务上,并将被抛出到await,从而使您能够流畅地处理它,同时也允许延续在原始上下文中运行。

示例

private async void Create_File_OnClick(object sender, RoutedEventArgs e)
{       
try
{
XmlCreator xmlCreator = new XmlCreator();
await xmlCreator.CreateXmlAysnc();
}
catch (Exception e)
{
MessageBox.Show(e.Message); 
}
}
public async Task CreateXmlAysnc()
{
...
await using FileStream fileStream = File.Open(filePath, FileMode.Create);
await xmlDocument.SaveAsync(fileStream, SaveOptions.None, CancellationToken.None);
}

最新更新