1

参考: C#汎用タイムアウトの実装

私は現在、AWS からメトリクスを取得するプロジェクトに取り組んでおり、私のプログラムは ListObjects へのいくつかの特定の呼び出しで停止しています。この目的でスレッド アボートを使用することを検討しているとスーパーバイザーに伝えたところ、このケースに固有のタイムアウト関数ではなく、一般的なタイムアウト関数を作成するように求められました。これは安全ではないようです。参照された質問から使用しているスニペットを完全には理解していないので、ここでは少しわかりません。

動かなくなったコードのコール スタック:

mscorlib.dll!System.Threading.Thread.Sleep(int ミリ秒タイムアウト) + 0x5 バイト AWSSDK.dll!Amazon.S3.AmazonS3Client.pauseOnRetry(int 再試行、int maxRetries、System.Net.HttpStatusCode ステータス、文字列 requestAddr、System.Net. WebHeaderCollection ヘッダー、System.Exception 原因) + 0x5b バイト
AWSSDK.dll!Amazon.S3.AmazonS3Client.handleRetry(Amazon.S3.Model.S3Request userRequest、System.Net.HttpWebRequest リクエスト、System.Net.WebHeaderCollection respHdrs、long orignalStreamPosition、int再試行、System.Net.HttpStatusCode statusCode、System.Exception cause) + 0x17e バイト AWSSDK.dll!Amazon.S3.AmazonS3Client.getResponseCallback(System.IAsyncResult 結果) + 0x57a バイト
AWSSDK.dll!Amazon.S3.AmazonS3Client.invoke(Amazon .S3.AmazonS3Client.S3AsyncResult s3AsyncResult, bool isRedirect) + 0xcde バイト
AWSSDK.dll!Amazon.S3.AmazonS3Client.getResponseCallback(System.IAsyncResult 結果) + 0x636 バイト
AWSSDK.dll!Amazon.S3.AmazonS3Client.invoke(Amazon.S3.AmazonS3Client.S3AsyncResult s3AsyncResult, bool isRedirect) + 0xcde バイト
AWSSDK.dll !Amazon.S3.AmazonS3Client.getResponseCallback(System.IAsyncResult 結果) + 0x636 バイト
AWSSDK.dll!Amazon.S3.AmazonS3Client.invoke(Amazon.S3.AmazonS3Client.S3AsyncResult s3AsyncResult, bool isRedirect) + 0xcde バイト
AWSSDK.dll!Amazon. S3.AmazonS3Client.getResponseCallback(System.IAsyncResult 結果) + 0x636 バイト
AWSSDK.dll!Amazon.S3.AmazonS3Client.invoke(Amazon.S3.AmazonS3Client.S3AsyncResult s3AsyncResult, bool isRedirect) + 0xcde バイト
AWSSDK.dll!Amazon.S3.AmazonS3Client.invoke(Amazon.S3.AmazonS3Client.S3AsyncResult s3AsyncResult) + 0x53 バイト
AWSSDK.dll!Amazon.S3.AmazonS3Client.invokeListObjects(Amazon.S3.Model.ListObjectsRequest リクエスト、System.AsyncCallback コールバック、オブジェクトの状態、bool 同期) + 0x102 バイト AWSSDK.dll!Amazon.S3.AmazonS3Client.ListObjects(Amazon.S3.Model.ListObjectsRequest リクエスト) + 0x31 バイト

まず、これを (Amazon の ListObjects のストール) に使用したい目的は、スレッドの中止に対して安全ですか?

第二に、非同期スレッドを中止せずにジェネリック関数でこれを行う安全な方法はありますか?

ここに私が持っているものがあります:

実装:

public static class Timeout<TResult>
{
    private static int _timeout = 5000;

    //WARNING - This method uses asynchronous thread aborting and can result
    //in roughhousing and !@#$ hitting the fan
    public static TResult Run(Func<TResult> function)
    {
        if (function == null) throw new ArgumentNullException("function to timeout is null");

        var sync = new object();
        var isCompleted = false;

        WaitCallback watcher = obj =>
        {
            var watchedThread = obj as Thread;

            lock (sync)
            {
                if (!isCompleted)
                {
                    Monitor.Wait(sync, _timeout);
                }
            }

            if (!isCompleted)
            {
                watchedThread.Abort();
            }
        };

        try
        {
            ThreadPool.QueueUserWorkItem(watcher, Thread.CurrentThread);
            return function();
        }
        catch (ThreadAbortException)
        {
            Thread.ResetAbort();
            return default(TResult);
        }
        finally
        {
            lock (sync)
            {
                isCompleted = true;
                Monitor.Pulse(sync);
            }
        }
    }
}

呼び出し:

response = Timeout<ListObjectsResponse>.Run(() => s3Client.ListObjects(request));
4

2 に答える 2

1

最初に注意していただきたいのは、実行時間の長いアプリケーションにとって、スレッドの中止は恐ろしいことです。あらゆる種類の元に戻せない状態の破損を引き起こす可能性があります (静的 ctor を中止して、クラス全体を永久にホース状態にするなど)。リンク先の「参照」の下にあるコメントを監督者に示します。

スレッドの中止でこれを実装しないでください。

代わりに、ワーカー関数を別のスレッドで開始します。タイマーを開始して、タイムアウト状態を検出します。経過したら、ワーカー スレッドを実行させますが、その結果を破棄してすぐに戻ります。

重要なのは、ワーカーを実行させ、その結果を破棄することです。

于 2013-01-04T17:27:48.447 に答える
0

ジェネリックを使用する必要はないと思います。AmazonAWSの根本的な問題の原因を見つけました。明らかに、バケットの名前にピリオドが含まれていて、リージョンがUS(east)でない場合は、クライアント用に特定のエンドポイントを構成する必要があります。

于 2013-01-04T18:54:35.940 に答える