[英](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.