参考: 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));