为什么异步处理程序在发生异常时正在执行循环?

时间:2011-06-19 12:40:41

标签: asp.net multithreading ihttpasynchandler

我有这个处理程序。我在内部类的'StartTransfer'方法中遇到异常(我标记了该点),并且由于原因我不知道它循环此方法。为什么它会循环而不只是在异常消息中响应?

public sealed class ImageUploadHandler : IHttpAsyncHandler
{
    public bool IsReusable { get { return false; } }

    public ImageUploadHandler()
    {
    }
    public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
    {
        string token = context.Request.Form["token"];
        string albumId = context.Request.Form["albumId"];
        string imageDescription = context.Request.Form["description"];
        HttpPostedFile imageFile = context.Request.Files["image"];

        ImageTransferOperation ito = new ImageTransferOperation(cb, context, extraData);
        ito.Start(token, albumId, imageDescription, imageFile);
        return ito;
    }

    public void EndProcessRequest(IAsyncResult result)
    {
    }

    public void ProcessRequest(HttpContext context)
    {
        throw new InvalidOperationException();
    }

    private class ImageTransferOperation : IAsyncResult
    {
        private Object state;
        private bool isCompleted;
        private AsyncCallback cb;
        private HttpContext context;

        public WaitHandle AsyncWaitHandle
        {
            get { return null; }
        }

        public bool CompletedSynchronously
        {
            get { return false; }
        }

        public bool IsCompleted
        {
            get { return isCompleted; }
        }

        public Object AsyncState
        {
            get { return state; }
        }

        public ImageTransferOperation(AsyncCallback cb, HttpContext context, Object state)
        {
            this.cb = cb;
            this.context = context;
            this.state = state;
            this.isCompleted = false;
        }

        public void Start(string token, string albumId, string description, HttpPostedFile file)
        {
            Dictionary<string, Object> dictionary = new Dictionary<string,object>(3);

            dictionary.Add("token", token);
            dictionary.Add("albumId", albumId);
            dictionary.Add("description", description);
            dictionary.Add("file", file);

            ThreadPool.QueueUserWorkItem(new WaitCallback(StartTransfer), dictionary);
        }

        private void StartTransfer(Object state)
        {
            Dictionary<string, Object> dictionary = (Dictionary<string, Object>)state;

            string token = (string)dictionary["token"];
            string albumId = (string)dictionary["albumId"];
            string description = (string)dictionary["description"];
            HttpPostedFile file = (HttpPostedFile)dictionary["file"];

            var media = new Facebook.FacebookMediaObject {
                FileName = file.FileName,
                ContentType = file.ContentType                  
            };

            using (var binaryReader = new BinaryReader(file.InputStream))
            {
                media.SetValue(binaryReader.ReadBytes(Convert.ToInt32(file.InputStream.Length)));
            }

            dictionary.Clear();

            dictionary.Add("message", description);
            dictionary.Add("source", media);

            var client = new Facebook.FacebookClient(token); // <-- Here is where the exception occured

            //var result = client.Post("/" + albumId + "/photos", dictionary);

            context.Response.ContentType = "text/plain";

            context.Response.Write(token + " | " + file.FileName);
            //context.Response.Write(result.ToString());

            isCompleted = true;
            cb(this);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

我无法诚实地解释您所描述的任何“循环”,但您可以处理异步代码中的任何异常。您必须处理异常并将它们传播回正在等待IAsyncResult

的线程

因此,首先,您需要在StartTransfer方法的大部分主体周围进行try / catch / finally,在此方法中捕获可能发生的任何潜在异常,将其存储在字段中,并且finally块,总是调用回调。现在您实际上捕获了任何潜在的异常并且总是回调,接下来需要进行测试以查看EndProcessRequest中是否发生异常并将其提升到那里以便回调可以“观察”它。 / p>

以下是对ImageTransferOperation课程的一些修订:

private Exception asyncException;

public Exception Exception
{
    get
    {
        return this.asyncException;
    }
}

private void StartTransfer(Object state)
{
    try
    {
        ... rest of implementation here ...
    }
    catch(Exception exception)
    {
        this.asyncException = exception;
    }
    finally
    {
        this.isCompleted = true;
        this.cb(this);
    }
}

然后到ImageUploadHandler传播异常:

public void EndProcessRequest(IAsyncResult result)
{
    ImageTransferOperation imageTransferOperation = (ImageTransferOperation)result;

    Exception exception = imageTransferOperation.Exception

    if(exception != null)
    {
        throw exception;
    }
}