3

asp.netアプリケーションで、データベースにできるだけ効率的にログインしたいと思います。基本的なADO.NETを使用してログデータベースに書き込み、この非同期を実行したいので、次のようにします。

        using (var conn = new SqlConnection(_connectionString)) {
            using (var cmd = new SqlCommand("INSERT INTO dbo.Logs (TimeStamp,ThreadId,Level,Message,Exception) VALUES (@TimeStamp,@ThreadId,@Level,@Message,@Exception)", conn)) {
                cmd.Parameters.AddWithValue("@TimeStamp", DateTime.UtcNow);
                cmd.Parameters.AddWithValue("@ThreadId", Thread.CurrentThread.ManagedThreadId);
                cmd.Parameters.AddWithValue("@Level", level);
                cmd.Parameters.AddWithValue("@Message", msg);
                cmd.Parameters.AddWithValue("@Exception", ex == null ? "" : ex.ToString());
                conn.Open();
                cmd.ExecuteNonQueryAsync();
            }
        }

ここで私の質問は、cmd.ExecuteNonQueryAsync()ステートメントで待機を実行する必要があるのか​​、それとも基本的にファイアアンドフォーゲットを実行する必要があるため待機を省略してもよいのかということです。

4

3 に答える 3

8

非同期操作を起動して忘れるのはOKではありません-例外で失敗する可能性があり、その場合はほぼ確実に何かをしたい(ユーザーに通知/再試行/爆破)。(さらに、誰かが特定のオプションを使用した場合、タスクの例外は最終的にプロセスを停止します)。

また:接続を閉じる責任は誰にありますか?

編集:接続を閉じる問題を明確にするために、usingステートメントをtry/で書き直しますfinally(これはまったく同じILではないことはわかっていますが、問題がどこにあるかを確認するのに十分近いです)-その場合、コードは大まかに次のようになります。

SqlConnection conn;
try {
    conn = new SqlConnection("connString");
    SqlCommand cmd;
    try {
        cmd = new SqlCommand("INSERT INTO dbo.Logs (TimeStamp,ThreadId,Level,Message,Exception) VALUES (@TimeStamp,@ThreadId,@Level,@Message,@Exception)", conn);
        cmd.AddParameters();
        conn.Open();
        cmd.ExecuteNonQueryAsync();
    } finally {
        if (cmd != null) cmd.Dispose();
 } finally {
    if (conn != null) conn.Close();
 }

cmd.Dispose()の直後に呼び出されていることがわかりますcmd.ExecuteNonQueryAsync()。それはどのように機能しますか?2つの可能性があります。

  1. どちらかcmd.Dispose()(設計または偶然による)はcmd.ExecuteNonQueryAsync、その作業を実行できるようになるまで戻りません。つまり、実際にはcmd.Dispose後から戻るだけcmd.ExecuteNonQueryAsyncです。その場合、コードは機能しますが、await/asyncのメリットはありません。
  2. または、完了cmd.Dispose()できない方法で実行されます。cmd.ExecuteNonQueryAsync()その場合、コードは機能しません。

どちらの場合も、プログラムは間違っています。正しく動作することを確認するには、タスクawaitを呼び出すか、呼び出す必要があります。Wait()

于 2013-01-05T20:00:48.727 に答える
3

他の人が述べているように、ELMAHやlog4netなどの安定した十分にテストされたライブラリを強く検討してください。独自のソリューションを作成する場合は、オーバーヘッドがはるかに少なく、関連するOS / .NET / IIS/ASP.NETイベントを簡単に含めることができるETWベースのソリューションを検討してください。データベースへのログ記録を完了しました。それは良い考えのように聞こえるようなものですが、あなたは将来的にロジスティックの問題に遭遇します。

あなたの実際の質問に答えるためawaitに、あなたがエラーに答える必要があるならば、それはそれに良いです。これが本当にファイアアンドフォーゲットである場合は、Task結果を無視することができます。メソッドがである場合、 ;asyncを無視するとコンパイラは警告を発します。Task警告を回避するには、未使用の変数に割り当てるだけです。

var _ = cmd.ExecuteNonQueryAsync();
于 2013-01-06T00:10:51.243 に答える
2

最も簡単な方法は、同期操作でTask.Run()を使用してファイアアンドフォーゲットを実行することです。

例えば、

Task.Run(() =>
{
     LogDatabase();

});

ここで、LogDatabase()は、ExecuteNonQuery()への同期標準ADO.NETです。

于 2013-06-25T03:06:16.000 に答える