0

I am new to C# and WinForms.I programmed a Progressbar that reads text from file and displays that text above the bar.That updating process happens on a separate thread, it updates it every 2s.It works but sometimes when I close the programm I get an error something like:accesing disposed object. The error occurs at the code I provided under this text specifically at Invoke(new MethodInvoker(()=>{UpdateMsgText(msgText);}));

private void UpdateMsgText(string msgText)
{
    if(InvokeRequired){
    Invoke(new MethodInvoker(()=>{UpdateMsgText(msgText);}));
}
else
{
    processingInfo.Text=msgText;
}

This is where the function is being called:

        private async void BackgroundWorker()
        {

            if (string.IsNullOrEmpty(m_Arguments.m_ProgressFilePath))
            {
                MessageBox.Show(GetValueFromResourceFile("WarningProgressPathNotProvided"));
                CloseForm();

            }

            while (IsFinsihed() == false && IsDisposed == false)
            {
                string progressText = ReadTextFromFile(m_Arguments.m_ProgressFilePath);
                string msgText = ReadTextFromFile(m_Arguments.m_MsgFilePath);

                int progress = 0;

                if (!string.IsNullOrEmpty(progressText))
                {
                    TryUpdateSingleValue(progressText, ref progress);
                }


                if (!string.IsNullOrEmpty(msgText))
                {
                    //if the text is to big to fit in progressViewer the UI will not display that text
                    if (!IsMessageTooLong(msgText))
                    {
                        UpdateMsgText(msgText);
                        m_MessageBoxTooLongTextShown = false;
                    }

                }
                if (progress >= 100)
                {
                    CloseForm();
                    break;
                }
                if (progress < 0)
                {
                    UpdateProgressBar(0);
                }

                await Task.Delay(m_Arguments.m_ThreadDelayTime);

            }

        }

I tried using if (InvokeRequired &&!isDisposed) and also try catch block but nothing worked.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
User23423
  • 1
  • 1
  • 1
    Use `async/await`, Task.Run and Progress instead of raw threads and `Invoke`. There's no need for Invoke for the last 10 years – Panagiotis Kanavos Jul 05 '23 at 09:16
  • What's the actual *full* exception text, including the call stack? If you use a timer, did you stop it after closing the form? Or is `UpdateMsgText` trying to update a form that no longer exists? – Panagiotis Kanavos Jul 05 '23 at 09:20
  • https://stackoverflow.com/a/1732361/17034 – Hans Passant Jul 05 '23 at 09:24
  • @ Panagiotis Kanavos it is run like this `Task.Run(Backgroundworker)` and the message comes sometimes "Cannot access a disposed object" – User23423 Jul 05 '23 at 09:26
  • You have to pass a `CancellationToken` and an `IProgress` delegate to the Task (your `BackgroundWorker` method must have a return Type of `Task`, not `void`). As mentioned, avoid invoking. Also, `InvokeRequired` doesn't *protect* you here. Store the `CancellationTokenSource`, then call its `Cancel()` method to stop the running Task when needed, e.g., when the Form closes -- You can take the example from here: [How to download files using HttpClient with a ProgressBar?](https://stackoverflow.com/a/74554087/7444103) as reference – Jimi Jul 05 '23 at 10:53
  • The `Progress` delegate method is called in the UI Thread. There, you can test whether a Control is disposed, in case this is still needed. You cannot do that from different Thread – Jimi Jul 05 '23 at 11:09

0 Answers0