在哪里停止使用async / await关键字?

我的DB2 / 400有一个简单的心跳方法:

public bool CheckConnection() { try { using (OleDbConnection db = new OleDbConnection( this.conString )) { OleDbCommand cmd = new OleDbCommand(); cmd.CommandText = "select 1 from sysibm.sysdummy1"; cmd.Connection = db; db.Open(); cmd.ExecuteReader(); db.Close(); return true; } } catch (Exception) { return false; } } 

我希望在我的应用程序运行时使用它,当然我不想执行表单的其余部分。

我的主要方法是:

 public FrmMain() { InitializeComponent(); PrepareFormTexts(); PrepareFormData(); PrepareStateClass(); CheckDbConnection(); //Initialize Data Access for AS400 Dal = JDE8Dal.Instance; Dal.conString = Properties.Settings.Default.conAS400; //Initialize Icons picCon.Image = Properties.Resources.ledGreen; picStatus.Image = Properties.Resources.ledGreen; // Load recording from file if they exist PrepareRecordings(AppState.DataFileName,'|'); } 

CheckDbConnection方法:

  private async Task CheckDbConnection() { return await Task.Factory .StartNew(() => Dal.CheckConnection()); } 

我认为它运行正常,但我收到警告

警告1由于未等待此调用,因此在完成调用之前将继续执行当前方法。 考虑将’await’运算符应用于调用的结果。

我应该忽略它吗? 我应该在主方法中放异步吗?

更新:在下面讨论后我发现,因为我使用.NET 4.0的异步包,我真的不能让我的dal方法无阻塞。 我唯一能做的就是使用async / await + task.factory.startnew,以便在dal在后台运行时保持我的应用程序正常工作。

代码如下:

 public FrmMain() { InitializeComponent(); Load += FormLoadInit; } private async void FormLoadInit(object sender, EventArgs e) { PrepareFormTexts(); PrepareFormData(); PrepareStateClass(); txtLot.Select(); //Initialize Data Access for AS400 Dal = JDE8Dal.Instance; Dal.conString = Properties.Settings.Default.conAS400; // Load recording from file if they exist PrepareRecordings(AppState.DataFileName, '|'); bool cn = await Task.Factory.StartNew(() => Dal.CheckConnection()); //Initialize Icons picCon.Image = cn ? Resources.ledGreen : Resources.ledRed; picStatus.Image = Properties.Resources.ledGreen; } 

警告告诉你的是你有效地解雇然后忘记了这个异步任务。 您实际上从未使用过操作的结果,甚至也没有存储Task本身以允许任何将来的代码依赖于它的结果(甚至知道它何时完成)。

这不会破坏任何东西,但它也不是真的有用。 您也可以不调用该方法。 现在,在你的情况下,这只是一个虚拟列表,所以你需要问自己你想要测试什么。 您是否希望在表单上显示一些虚拟值作为概念certificate? 如果是这样,您的代码将需要一些更改才能实现。

要实际使用查询结果,您需要await它,而不能在构造函数中执行此操作。 您需要将代码移动到Form Load事件处理程序并将处理程序标记为async以便您可以在其中await

您遇到的另一个问题是,要创建异步方法,您将启动一个新任务,该任务将在线程池中运行,然后让它执行阻塞方法。 使用async / await模型的主要优点是您不需要这样做。 您应该使用数据库查询方法直接为您提供Task作为其返回值并且不阻止。 然后,您可以await这些任务(或只是返回它们),以便您的应用程序在您等待时不会阻塞任何线程。

您的CheckConnection方法应如下所示:

 public async Task CheckConnection() { try { using (OleDbConnection db = new OleDbConnection(this.conString)) { OleDbCommand cmd = new OleDbCommand(); cmd.CommandText = "select 1 from sysibm.sysdummy1"; cmd.Connection = db; db.Open(); await cmd.ExecuteReaderAsync(); return true; } } catch (Exception) { return false; } } 

CheckDbConnection则不需要存在。 没有必要在Task包装CheckConnection ,因为它已经返回任务。

构造函数不能是Async(至少我每次尝试都会遇到编译错误。但是事件处理程序可以。我认为大多数初始化代码都属于Form.Load处理程序。

 public FrmMain() { InitializeComponent(); Load+=OnLoaded; } private async void Onloaded(object sender, EventArgs args) { PrepareFormTexts(); PrepareFormData(); PrepareStateClass(); await CheckDbConnection(); //Initialize Data Access for AS400 Dal = JDE8Dal.Instance; Dal.conString = Properties.Settings.Default.conAS400; //Initialize Icons picCon.Image = Properties.Resources.ledGreen; picStatus.Image = Properties.Resources.ledGreen; // Load recording from file if they exist PrepareRecordings(AppState.DataFileName,'|'); } 
 public FrmMain() { InitializeComponent(); PrepareFormTexts(); PrepareFormData(); PrepareStateClass(); Task delayTask = CheckDbConnection(); //Initialize Data Access for AS400 Dal = JDE8Dal.Instance; Dal.conString = Properties.Settings.Default.conAS400; //Initialize Icons picCon.Image = Properties.Resources.ledGreen; picStatus.Image = Properties.Resources.ledGreen; // Load recording from file if they exist PrepareRecordings(AppState.DataFileName,'|'); } 

为了实现您的范围,您可能应该考虑Reactive Extensions Framework 。 以下是基于您的问题示例的示例实现。 您需要向表单添加标签( label1label2 )。

 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; //get Reactive Extensions and reference them in your project. //Reactive Extensions for .NET (Rx .NET) http://msdn.microsoft.com/en-us/data/gg577610 using System.Reactive.Linq; namespace WindowsFormsApplication2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); Load += Form1_Load; } async void Form1_Load(object sender, EventArgs e) { //do independent stuff PrepareSomeStuff(); //notify the DB checking label1.Text = "Checking DB"; //declare an IObservable IObservable startAsync = Observable.Start(() => CheckConnection()).FirstAsync(); //do some other independent stuff PrepareSomeOtherStuff(); //wait for the IObservable to return data bool isDbReady = await startAsync; label1.Text = "Ready"; } private void PrepareSomeOtherStuff() { //do some other stuff label2.Text += "\r\nDo some other stuff"; } private void PrepareSomeStuff() { //do stuff label2.Text = "Do stuff"; } private bool CheckConnection() { //do stufff System.Threading.Thread.Sleep(5000); return true; } } }