0

Following is the code for my ThreadSafe function

public static void ThreadSafe(Action action)
        {
             System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
             new MethodInvoker(action));
        }

I am using this ThreadSafe function to access various cross-thread actions. Its working fine in other classes but when I am adding a user control Comment in panel commentContainer, its showing following error.

Cross-thread operation not valid exception

Following its screenshot with the code: enter image description here

I want to pass the comment string to this control. The control processing is based on this value. I think my way of using this function is wrong. Can any one please improve my code if its not correct? And if correct then please tell me what to do to solve this issue?

Also note that when I removed the foreach loop, the background worker is working fine.

setTopicInfo() code:

public void setTopicInfo()
        {
            try
            {
                TopicInfo.Text = "Topic Views: " + dops.getVisiteds(tid) + " | " +
                    "People Involved: " + dops.getPeopleInvolved(tid) + " | ";
            }
            catch (Exception)
            { TopicInfo.Text = "[Some error occured while loading Topic Information. Please reopen or refresh this topic.] | "; }
        }
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
Shiva Pareek
  • 1,719
  • 5
  • 21
  • 42

3 Answers3

2

Dispatcher.CurrentDispatcher returns a Dispatcher for the current thread. In this example, the ThreadSafe method was invoking the Action on the current thread rather than on the thread that created commentContainer (usually referred to as the UI thread.)

WinForms facilitates invoking code on the UI thread through the Control.Invoke and Control.BeginInvoke methods. A quick one-line fix to this example is replacing the call to Main.ThreadSafe with a call to commentContainer.Invoke or commentContainer.BeginInvoke. You may also take advantage of the BackgroundWorker.ProgressChanged event, as suggest by Bill Sambrone.

JosephHirn
  • 720
  • 3
  • 9
1

Your ThreadSafe method establishes a Dispatcher while it is called from a bgw thread.

And this is what MSDN has to say about Dispatcher.CurrentDispatcher :

If a Dispatcher is not associated with the current thread, a new Dispatcher will be created.

Use Application.Dispatcher instead. See for example this SO question.

Community
  • 1
  • 1
H H
  • 263,252
  • 30
  • 330
  • 514
  • 1
    The question is about WinForms, so `Application.Current` will probably be null. (I'm assuming you meant `Application.Current.Dispatcher` as in that other question.) –  Aug 01 '13 at 14:17
  • Dispatcher and Current doesn't exits in Application Class. – Shiva Pareek Aug 01 '13 at 14:19
  • Sorry, I missed the WinForms tag. Still, same problem, other solution. – H H Aug 01 '13 at 14:22
  • 1
    @ShivaPareek That's probably because you're looking at `System.Windows.Forms.Application` rather than `System.Windows.Application`. (But like I said, if you did use `System.Windows.Application`, that probably still wouldn't help you. Go with Ginosaji's comments on your question.) –  Aug 01 '13 at 14:22
1

Since you are using a BackgroundWorker, you can set the comment using its ability to report progress. Either create the ReportProgress event handler through the designer or add it in code if you are creating your BWWorker from code. Make sure you enable the flag for ReportsProgress.

Then, in your foreach loop:

backgroundWorker1.ReportProgress(yourdatagoeshere)

In the backgroundWorker1_ReportsProgress method, you would then pass that data to your addComment method.

Bill Sambrone
  • 4,334
  • 4
  • 48
  • 70