ObjectDisposeException System.Threading.Timer.throwIfDispose() 被抛出

发布于 2024-10-18 09:38:10 字数 4192 浏览 3 评论 0原文

我抛出了一个可怕的异常,不知道如何修复它:(

System.ObjectDisposedException 
ObjectDisposedException-   at System.Threading.Timer.throwIfDisposed()
   at System.Threading.Timer.Change(UInt32 dueTime, UInt32 period)
   at System.Threading.Timer.Change(Int32 dueTime, Int32 period)
   at System.Net.HttpWebRequest.ConnectionClient.Read(Byte[] data, Int32 offset, Int32 length)
   at System.Net.HttpReadStream.NetworkRead(Byte[] data, Int32 offset, Int32 length)
   at System.Net.ContentLengthReadStream.doRead(Byte[] data, Int32 offset, Int32 length)
   at System.Net.HttpReadStream.ReadToDrain(Byte[] buffer, Int32 offset, Int32 length)
   at System.Net.HttpReadStream.doClose()
   at System.Net.ContentLengthReadStream.doClose()
   at System.Net.HttpReadStream.Finalize()

我读到,当您尝试重用 HttpWebRequest 或类似的东西时,就会发生这种情况,但我已经加倍了三重检查了整个项目,我没有重用任何 HttpWebRequest

我正在一个单独的线程上下载 HTML,有时我需要中止该线程,但我调用 Join,所以这不应该是一个大问题问题对吗?

有什么方法可以捕获这个异常或者不让它被抛出吗?或者有什么方法可以准确地找到它是从哪里抛出的(HttpWebRequest的哪个实例或什么对象抛出的)这个)

编辑:

好的,更多关于正在发生的事情,我正在 UI 之外的单独线程上进行 HttpWebRequest 调用(像大多数人一样),但是当我关闭应用程序时,它会挂起,因为 HTTP请求没有成功或超时,所以我决定中止它们(这是一个暴力的词,你不觉得吗?)那就是异常开始发生的时候,如果有更好的方法来做到这一点,我会洗耳恭听。 !

这是我调用的方法之一,有时会被中断。我运行这个直到最多有 6 个线程:

private static void startImageDownloading()
{
    ThreadStart start = () =>
    {
        while (_list.Count > 0) // _list contains all of the images that need to be downloaded
        {
            ImageRequest req; // ImageRequests are containers that hold all the request info
            lock (_list)
            {
                if (_list.Count > 0)
                    req = _list.Dequeue();
                else continue;
            }

            if (req.Item.Parent.IsDisposed)
                continue;

            using (MemoryStream i = getImageWeb(req))
                if (i != null)
                {
                    foreach (var callback in req.Callbacks)
                        callback(i);    //  Callbacks is a List<ImageDelegate> object

                    if (req.Item.Parent != null && !req.Item.Parent.IsDisposed)
                        req.Item.Parent.Damage();   //  Cross thread Invalidate call
                }
        }

        Thread.CurrentThread.Priority = ThreadPriority.Lowest;
    };

    Thread t = new Thread(start) { IsBackground = true, Priority = ThreadPriority.BelowNormal };

    t.Start();

    _downloadThreads.Add(t);
}

这是 getImageWeb:

private static MemoryStream getImageWeb(ImageRequest req)
{
    int tries = 0;
    try
    {
        MemoryStream ret = null;
        while (tries < maxRetries && (ret = downloadImageFile(req.Uri)) == null && !req.Cancelled)
            tries++;

        return ret;
    }
    catch { }

    return null;
}

最后是 downloadImageFile:

private static MemoryStream downloadImageFile(string url)
{
    MemoryStream ret = null;

    try
    {
        var uri = new Uri(url);

        var webRequest = (HttpWebRequest)WebRequest.Create(uri);
        webRequest.Method = "GET";
        webRequest.Timeout = 10000;
        webRequest.ProtocolVersion = HttpVersion.Version10;
        webRequest.Proxy = null;
        using (var webResponse = (HttpWebResponse)webRequest.GetResponse())
        {
            if (webResponse.StatusCode.ToString().Equals("OK"))
            {
                ret = new MemoryStream();
                using (Stream responseStream = webResponse.GetResponseStream())
                {
                    if (responseStream == null)
                        return null;
                    CopyStream(responseStream, ret);
                }
                ret.Position = 0;
            }
        }
    }
    catch (WebException e)
    {
        string error = "";
        if (e.Response != null)
            using (var response = e.Response)
            using (var resp = response.GetResponseStream())
            using (var errorStream = new StreamReader(resp))
                error = errorStream.ReadToEnd();
    }
    catch (Exception exp)
    {
    }

    return ret;
}

I'm getting a terrible exception thrown and IDK what to do to fix it :(

System.ObjectDisposedException 
ObjectDisposedException-   at System.Threading.Timer.throwIfDisposed()
   at System.Threading.Timer.Change(UInt32 dueTime, UInt32 period)
   at System.Threading.Timer.Change(Int32 dueTime, Int32 period)
   at System.Net.HttpWebRequest.ConnectionClient.Read(Byte[] data, Int32 offset, Int32 length)
   at System.Net.HttpReadStream.NetworkRead(Byte[] data, Int32 offset, Int32 length)
   at System.Net.ContentLengthReadStream.doRead(Byte[] data, Int32 offset, Int32 length)
   at System.Net.HttpReadStream.ReadToDrain(Byte[] buffer, Int32 offset, Int32 length)
   at System.Net.HttpReadStream.doClose()
   at System.Net.ContentLengthReadStream.doClose()
   at System.Net.HttpReadStream.Finalize()

I've read that this occurs when you try and reuse an HttpWebRequest or something like that, but I've double and triple checked the whole project and I'm not reusing any HttpWebRequest

I am downloading HTML on a separate thread, and sometimes I need to abort that thread, but I call Join so that shouldn't be a big issue right?

Is there any way to catch this Exception or have it not be thrown? Or is there any way I can find exactly where it is been thrown from (which instance of HttpWebRequest or what ever object throws this)

EDIT:

Ok, a little more about what's going on. I'm making HttpWebRequest calls on separate threads off the UI (like most people) but when I close the application, it hangs because the HTTP requests haven't succeeded or timed out. So I decided to Abort them (such a violent word, don't you think?) Thats when the exceptions started happening. If there is a better way to do it, i'm all ears!

Here is one of the methods that I'm calling that sometimes gets interrupted. I run this until there are at most 6 threads:

private static void startImageDownloading()
{
    ThreadStart start = () =>
    {
        while (_list.Count > 0) // _list contains all of the images that need to be downloaded
        {
            ImageRequest req; // ImageRequests are containers that hold all the request info
            lock (_list)
            {
                if (_list.Count > 0)
                    req = _list.Dequeue();
                else continue;
            }

            if (req.Item.Parent.IsDisposed)
                continue;

            using (MemoryStream i = getImageWeb(req))
                if (i != null)
                {
                    foreach (var callback in req.Callbacks)
                        callback(i);    //  Callbacks is a List<ImageDelegate> object

                    if (req.Item.Parent != null && !req.Item.Parent.IsDisposed)
                        req.Item.Parent.Damage();   //  Cross thread Invalidate call
                }
        }

        Thread.CurrentThread.Priority = ThreadPriority.Lowest;
    };

    Thread t = new Thread(start) { IsBackground = true, Priority = ThreadPriority.BelowNormal };

    t.Start();

    _downloadThreads.Add(t);
}

Here is the getImageWeb:

private static MemoryStream getImageWeb(ImageRequest req)
{
    int tries = 0;
    try
    {
        MemoryStream ret = null;
        while (tries < maxRetries && (ret = downloadImageFile(req.Uri)) == null && !req.Cancelled)
            tries++;

        return ret;
    }
    catch { }

    return null;
}

And finally downloadImageFile:

private static MemoryStream downloadImageFile(string url)
{
    MemoryStream ret = null;

    try
    {
        var uri = new Uri(url);

        var webRequest = (HttpWebRequest)WebRequest.Create(uri);
        webRequest.Method = "GET";
        webRequest.Timeout = 10000;
        webRequest.ProtocolVersion = HttpVersion.Version10;
        webRequest.Proxy = null;
        using (var webResponse = (HttpWebResponse)webRequest.GetResponse())
        {
            if (webResponse.StatusCode.ToString().Equals("OK"))
            {
                ret = new MemoryStream();
                using (Stream responseStream = webResponse.GetResponseStream())
                {
                    if (responseStream == null)
                        return null;
                    CopyStream(responseStream, ret);
                }
                ret.Position = 0;
            }
        }
    }
    catch (WebException e)
    {
        string error = "";
        if (e.Response != null)
            using (var response = e.Response)
            using (var resp = response.GetResponseStream())
            using (var errorStream = new StreamReader(resp))
                error = errorStream.ReadToEnd();
    }
    catch (Exception exp)
    {
    }

    return ret;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

毁我热情 2024-10-25 09:38:10

中止线程会导致自动处置任何[非共享]引用的对象(如果该对象实现了 IDisposable )。有一个计时器被配置为按时间间隔执行某些操作(似乎是一些异步网络活动)。中止线程会导致计时器被释放,这就是异常的原因。

尝试调用适当的断开连接方法而不是中止线程。作为一般规则,永远不要中止线程,除非您确定线程在哪里以及阻止它完成工作的后果是什么。需要更多详细信息才能更准确地讨论您的案例。

Aborting a thread causes any [non-shared] referenced objects to be disposed automatically (if IDisposable is implemented by that object). There's a timer which is configured to do something in intervals (it seems some async network activity). Aboting the thread caused that timer to be disposed and this is the reason for exception.

Try to call appropriate disconnecting method instead of aborting the thread. As a general rule never abort a thread unless you are sure where it is and what's the consequences of stopping it from finishing his job. More details is needed for talking more precise about your case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文