参考: Implement C# Generic Timeout
我目前正在开发一个从AWS中提取指标的项目,而我的程序只停留在对ListObjects的一些特定调用上。我告诉我的主管我正在考虑为此目的使用线程中止,现在他要求我编写一个通用的超时功能,而不是一个特定的情况。这似乎不安全。现在我并不完全理解我在引用的问题中使用的片段,所以我在这里有点黑暗。
在卡住的代码上调用堆栈:
mscorlib.dll!System.Threading.Thread.Sleep(int millisecondsTimeout)+ 0x5 bytes AWSSDK.dll!Amazon.S3.AmazonS3Client.pauseOnRetry(int retries,int maxRetries,System.Net.HttpStatusCode status,string requestAddr,System.Net.WebHeaderCollection headers,System.Exception cause)+ 0x5b bytes
AWSSDK.dll!Amazon.S3.AmazonS3Client.handleRetry(Amazon.S3.Model.S3Request userRequest,System.Net.HttpWebRequest request,System.Net.WebHeaderCollection respHdrs,long orignalStreamPosition,int retries,System.Net.HttpStatusCode statusCode,System。异常原因)+ 0x17e字节 AWSSDK.dll!Amazon.S3.AmazonS3Client.getResponseCallback(System.IAsyncResult result)+ 0x57a bytes
AWSSDK.dll!Amazon.S3.AmazonS3Client.invoke(Amazon.S3.AmazonS3Client.S3AsyncResult s3AsyncResult,bool isRedirect)+ 0xcde bytes
AWSSDK.dll!Amazon.S3.AmazonS3Client.getResponseCallback(System.IAsyncResult result)+ 0x636 bytes
AWSSDK.dll!Amazon.S3.AmazonS3Client.invoke(Amazon.S3.AmazonS3Client.S3AsyncResult s3AsyncResult,bool isRedirect)+ 0xcde bytes
AWSSDK.dll!Amazon.S3.AmazonS3Client.getResponseCallback(System.IAsyncResult result)+ 0x636 bytes
AWSSDK.dll!Amazon.S3.AmazonS3Client.invoke(Amazon.S3.AmazonS3Client.S3AsyncResult s3AsyncResult,bool isRedirect)+ 0xcde bytes
AWSSDK.dll!Amazon.S3.AmazonS3Client.getResponseCallback(System.IAsyncResult result)+ 0x636 bytes
AWSSDK.dll!Amazon.S3.AmazonS3Client.invoke(Amazon.S3.AmazonS3Client.S3AsyncResult s3AsyncResult,bool isRedirect)+ 0xcde bytes
AWSSDK.dll!Amazon.S3.AmazonS3Client.invoke(Amazon.S3.AmazonS3Client.S3AsyncResult s3AsyncResult)+ 0x53 bytes
AWSSDK.dll!Amazon.S3.AmazonS3Client.invokeListObjects(Amazon.S3.Model.ListObjectsRequest请求,System.AsyncCallback回调,对象状态,bool同步)+ 0x102字节 AWSSDK.dll!Amazon.S3.AmazonS3Client.ListObjects(Amazon.S3.Model.ListObjectsRequest request)+ 0x31 bytes
首先,我想将这个用于(亚马逊的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));
答案 0 :(得分:1)
首先请注意,线程中止对于长时间运行的应用程序来说是一件可怕的事情。它可能导致各种不可逆转的状态腐败(比如中止一个静态的ctor,导致整个类被永远地冲洗)。向您的主管显示您链接到的“参考”下方的评论。
不要通过线程中止来实现它。
相反,在单独的线程上启动worker函数。启动计时器以检测超时情况。当它过去时,让工作线程运行但丢弃其结果并立即返回。
关键是让工人跑步,但要丢弃其结果。
答案 1 :(得分:0)
嗯,我想我不需要使用泛型,我发现了亚马逊AWS的根本问题的原因。显然,如果存储桶的名称中包含一个句点且该区域不是US(东),则需要为客户端配置特定端点。