简体   繁体   English

(调用)无法访问已处置的对象

[英](Invoke) Cannot access a disposed object

I was trying the FileTransferManager library, which is used to transfer files/folders.我正在尝试FileTransferManager库,它用于传输文件/文件夹。 When I close my form while a copy is in progress sometimes I get this error:当我在复制过程中关闭表单时,有时会出现此错误:

Cannot access a disposed object.无法访问已处置的对象。 Object name: 'formMain'.对象名称:'formMain'。

And the weird part as I mentioned earlier, I don't always get this error.正如我之前提到的奇怪的部分,我并不总是收到这个错误。 Sometimes, the form closes without any issues.有时,表单关闭没有任何问题。

I tried to check if formMain is actually disposed using this.IsDisposed at the time when the error occurs, but it always returns false .我试图在发生错误时检查 formMain 是否实际使用this.IsDisposed进行了处理,但它始终返回false I even tried to put that check in the delegate but it didn't help.我什至试图将该支票放在委托中,但没有帮助。

Here's the StackTrace:这是堆栈跟踪:

   at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
   at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
   at DirCopyTest.formMain.SetProgressBarValue(ProgressBar progressBar, Int32 val) in C:\Users\me\Documents\Visual Studio 2019\Projects\FileTransferManagerDemo\formMain.cs:line 73
   at DirCopyTest.formMain.TransferProgressChanged(TransferProgress tp) in C:\Users\me\Documents\Visual Studio 2019\Projects\FileTransferManagerDemo\formMain.cs:line 60
   at IOExtensions.FileTransferManager.<>c__DisplayClass7_0.<CopyFileWithProgress>b__0(Int64 size, Int64 transferred, Int64 streamSize, Int64 bytesTransferred, UInt32 number, CopyProgressCallbackReason reason, IntPtr file, IntPtr destinationFile, IntPtr data)

This is the specific line that causes the error:这是导致错误的特定行:

Invoke(new SetProgressBarCallback(SetProgressBarValue), new object[] { progressBar, val });

And here is the full code:这是完整的代码:

    CancellationTokenSource canceller;

    private async void buttonCopy_Click(object sender, EventArgs e)
    {
        canceller = new CancellationTokenSource();
        Action<TransferProgress> progress = new Action<TransferProgress>(TransferProgressChanged);

        await FileTransferManager.CopyWithProgressAsync(source, destination, progress, canceller.Token, false, true);
    }

    void TransferProgressChanged(TransferProgress tp)
    {
        if (!canceller.IsCancellationRequested)
           SetProgressBarValue(progressBar1, (int)tp.Percentage);
    }

    delegate void SetProgressBarCallback(ProgressBar progressBar, int val);

    private void SetProgressBarValue(ProgressBar progressBar, int val)
    {
        if (progressBar.InvokeRequired)
            Invoke(new SetProgressBarCallback(SetProgressBarValue), new object[] { progressBar, val });
        else
            progressBar.Value = val;  
    }

    private void formMain_FormClosing(object sender, FormClosingEventArgs e)
    {
        canceller.Cancel();
    }

What you have here is a good old-fashioned race condition between你在这里拥有的是一个很好的老式竞争条件

if (!canceller.IsCancellationRequested)

and

progressBar.Value = val; 

You could do a final check just before the later, it will shorten the window but not mitigate it.您可以在稍后之前进行最后检查,它会缩短窗口但不会减轻它。

if (!canceller.IsCancellationRequested)
   progressBar.Value = val;  

And / or you could just wrap the Value = val update in a try and catch on ObjectDisposedException and write-it-off和/或您可以将Value = val更新包装在try catch ObjectDisposedException并注销

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM