4

いくつかのアクションを同期的に実行する方法が必要です。これは0.5秒で完了するはずですが、数分間ぶらぶらする可能性があります。タイムアウトした場合、結果は気にしません。これが、コンパイラによって生成されたデリゲートを使用して現在実行していることです。BeginInvoke:

static void Main()
{
    bool disposed = false;
    var wait = new ManualResetEvent(false);
    var a = new Action(
        () =>
            {
                Thread.Sleep(1000); // <- some looong action

                if (!disposed)
                    lock (wait)
                        if (!disposed)
                            wait.Set();
            });

    a.BeginInvoke(a.EndInvoke, null);

    bool success = wait.WaitOne(500);
    Console.WriteLine(success ? "success" : "timeout");

    lock (wait)
    {
        wait.Dispose();
        disposed = true;
    }

    Console.ReadLine();
}

醜いですね。そして、ラムダクロージャの変数が変更されていることを知ってdisposedいます(私のReSharperとは異なり、このC#機能が好きです)。すべて私が処分したいからManualResetEventです。.NET4でより良いアプローチを提案できますか?おそらく、イベントの破棄をスキップして、GCに依存する必要がありますか?

注:ManualResetEvent.Set()破棄されたインスタンスで実行しようとすると爆発します。

4

2 に答える 2

4

いいえ、Disposeの呼び出しをスキップして、GCに依存しないでください。それはリソースの無駄であり、単純明快です。

.NET 4.0では、4.0の新機能であるSystem.Threadingアセンブリにあるタスク並列ライブラリを確認します。

具体的には、TaskクラスWaitメソッドを確認します。これにより、タイムアウトを指定できます。

また、タイムアウトした場合にタスクをキャンセルする方法も確認する必要があります。

于 2010-05-28T15:48:26.670 に答える
2

うーん、コンパイラで生成されたコードサンプルをもう少し調べたので、それが私の目標にぴったり合っているdelegate.BeginInvokeことがわかります。IAsyncResultAsyncWaitHandle

var a = new Action(() => Thread.Sleep(1000)); // <- some looong action
IAsyncResult asyncResult = a.BeginInvoke(a.EndInvoke, null);
bool success = asyncResult.AsyncWaitHandle.WaitOne(500);

の場合のその待機ハンドルは、実際には、非同期呼び出しが完了したときにスレッドプールスレッドから自動的に破棄されるAsyncResultインスタンスです。ManualResetEvent

于 2010-05-28T16:13:49.773 に答える