4

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<bool> 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;

    }
4

4 に答える 4

3

警告が伝えているのは、この非同期タスクを事実上起動してから忘れているということです。操作の結果を実際に使用することはなく、Taskそれ自体を保存して、将来のコードがその結果に依存できるようにすることもありません (または、いつ終了したかを知ることさえできません)。

これは何も壊しませんが、あまり役に立ちません。メソッドを呼び出さないこともできます。さて、あなたの場合、これは単なるダミー リストなので、何をテストしようとしているのかを自問する必要があります。概念の証明として、フォームにダミーの値を表示しますか? その場合、そこに到達するにはコードにいくつかの変更が必要になります。

クエリの結果を実際に使用するには、それが必要awaitですが、コンストラクター内からそれを行うことはできません。コードをForm Loadイベント ハンドラーに移動し、ハンドラーを としてマークして、その中asyncに入れることができawaitます。

もう 1 つの問題は、非同期メソッドを作成するために、スレッド プールで実行される新しいタスクを開始してから、ブロッキング メソッドを実行することです。async/await モデルを使用する主な利点は、その必要がないことです。Task<T>戻り値として a を直接与え、ブロックしないデータベースクエリメソッドを使用する必要があります。次にawait、待機中にアプリケーションがブロックされるスレッドがないように、それらのタスクを実行する (または単に返す) ことができます。

メソッドCheckConnectionは次のようになります。

public async Task<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();
            await cmd.ExecuteReaderAsync();
            return true;
        }
    }
    catch (Exception)
    {
        return false;
    }
}

CheckDbConnection存在する必要はありません。すでにタスクを返しているためCheckConnection、 a でラップする必要はありません。Task

于 2012-12-04T19:49:32.883 に答える
0
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,'|');
}
于 2012-12-04T19:56:22.173 に答える
0

スコープを達成するには、Reactive Extensions Frameworkを検討する必要があるかもしれません。以下は、質問の例に基づくサンプル実装です。フォームにラベルを追加する必要があります (label1およびlabel2)。

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<bool> startAsync = Observable.Start<bool>(() => CheckConnection()).FirstAsync<bool>();

            //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;
        }
    }
}
于 2012-12-04T21:52:46.043 に答える
0

コンストラクターを非同期にすることはできません (少なくとも、試行するたびに常にコンパイラ エラーが発生します。しかし、イベント ハンドラーは非同期にすることができます。とにかく、その初期化コードのほとんどは 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,'|');
}
于 2012-12-04T19:50:21.073 に答える