InvalidOperationException when multithreading in WPF

牧云@^-^@ 提交于 2020-01-16 13:15:13

问题


So I'm working on my first multithreaded WPF app. Please bear in mind I have little to no understanding of how to implement multithreading - I've done it in a few apps and always work off the existing code. This is my first attempt at it in WPF which is apparently quite different to Windows Forms...

So basically I'm working on this example which oddly enough doesn't mention that you have to instantiate a new thread and start it - I guess the author felt that was self evident even to newbies like myself.

In any case, it works okay until I get to the point where I want to update the properties of my UI controls at which point I'm hit with an InvalidOperationException that says the calling thread can't access the control because the control belongs to a different thread

So basically this is not a thread safe way to work, but I'm at a loss as to how I should fix this...

Here's my code:

string fn = "";

private void btnBrowse_Click(object sender, RoutedEventArgs e)
{
    if (lblActivity.Visibility != System.Windows.Visibility.Hidden)
    {
        lblActivity.Visibility = System.Windows.Visibility.Hidden;
    }
    if (lstResult.Items.Count != 0)
    {
        lstResult.Items.Clear();
    }

    OpenFileDialog ofd = new OpenFileDialog();

    Nullable<bool> result = ofd.ShowDialog();

    if (result == true)
    {
        txtSource.Text = ofd.FileName;
        txtDest.Text = ofd.FileName;
        fn = ofd.SafeFileName;

        PopulateControlsDuingLongRefreshCall("read");
    }
}

private void PopulateControlsDuingLongRefreshCall(string action)
{
    ShowProcessing();

    ThreadStart ts = delegate
    {
        switch (action)
        {
            case "format":
                Populate();
                CleanData();
                break;
            case "read":
                TextReader tr = new StreamReader(txtSource.Text);
                txtPreview.Text = tr.ReadToEnd();
                break;
        }

        Dispatcher.BeginInvoke(DispatcherPriority.Normal, (EventHandler)delegate
        {
            HideProcessing();
        }, null, null);

    };
    Thread thr = new Thread(ts);
    thr.Start();
}

private void ShowProcessing()
{
    recProcessing.Visibility = Visibility.Visible;
}
private void HideProcessing()
{
    recProcessing.Visibility = Visibility.Collapsed;
}

If anyone can suggest a solution here or explain more about the concept I'm using (I'm still pretty fuzzy on it) so that I can understand enough to find a solution on my own, that'd be much appreciated.

Thanks in advance!

EDIT
The error also comes up if I'm getting the UI control properties TextReader tr = new StreamReader(txtSource.Text); also throws the exception.


回答1:


In your delegate, rather than access txtSource directly, try using the following function to return a streamreader:

    private StreamReader GetTxtSource()
    {
        if (!this.Dispatcher.CheckAccess())
        {
            return this.Dispatcher.Invoke(new Func<StreamReader>(this.GetTxtSource)) as StreamReader;                
        }
        return new StreamReader(txtSource.Text);
    }

You might need to use txtSource.Dispatcher.CheckAccess() instead.




回答2:


What you really need to understand here, is that you CANNOT access any control from another thread than the UI thread.

So when you're doing

 case "read":
            TextReader tr = new StreamReader(txtSource.Text);
            txtPreview.Text = tr.ReadToEnd();
            break;

you're trying to set the value of a Textbox (txtPreview), in the background thread.

What you need to do, is to read the file content in the background thread, and then use the UI thread to update the textbox value, by using the Dispatcher:

 case "read":
            TextReader tr = new StreamReader(txtSource.Text);
            string content = tr.ReadToEnd();

            Dispatcher.Invoke((Action)(() =>
            {
                txtPreview.Text = content;
            }));
            txtPreview.Text = tr.ReadToEnd();
            break;


来源:https://stackoverflow.com/questions/14773183/invalidoperationexception-when-multithreading-in-wpf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!