1

参考: 实现 C# 通用超时

我目前正在从事一个从 AWS 提取指标的项目,而我的程序只是在对 ListObjects 的一些特定调用上停滞不前。我告诉我的主管,我正在考虑为此目的使用线程中止,现在他要求我编写一个通用的超时函数,而不是一个特定于这种情况的超时函数。这似乎并不安全。现在我不完全理解我在引用问题中使用的片段,所以我在这里有点摸不着头脑。

在卡住的代码上调用堆栈:

mscorlib.dll!System.Threading.Thread.Sleep(int millisecondsTimeout) + 0x5 字节 AWSSDK.dll!Amazon.S3.AmazonS3Client.pauseOnRetry(int retries, int maxRetries, System.Net.HttpStatusCode status, string 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 原因)+ 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 回调,对象状态,布尔同步)+ 0x102 字节 AWSSDK.dll!Amazon.S3.AmazonS3Client.ListObjects(Amazon.S3.Model.ListObjectsRequest 请求)+ 0x31 字节

首先,我想将其用于(亚马逊的 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

好吧,我想我不需要使用泛型,我找到了亚马逊 AWS 根本问题的原因。显然,如果存储桶的名称中有句点并且区域不是美国(东部),则需要为客户端配置特定的端点。

于 2013-01-04T18:54:35.940 回答