Posts Tagged ‘Windows Application’

Cross-thread operation not valid

Wednesday, May 14th, 2008

Sometimes you need to create a new thread in a windows form to do a parallel job, and (usually) want to update some windows controls based on what the worker thread is doing (typically incrementing a progress bar). There are two simple ways to access a control from a worker thread:

1) Passing the control to the thread:

Thread workerThread = new Thread(WorkerMethod);
workerThread.Start(myProgressBar);

The WorkerMethod being:

void WorkerMethod(object myProgressBar)
{...}

2)Providing an event which the worker method fires and the windows form handles - preferred:
Event Declaration (in the class containing the WorkerMethod):

event EventHandler UpdateUI;

Event firing (in WorkerMethod whenever needed):

if(UpdateUI != null)
UpdateUI(this, new EventArgs());

Subscribing to the event (in the windows form):

UpdateUI += new EventHandler(MyForm_UpdateUI);

Handling the event (in the windows form):

private void MyForm_UpdateUI(object sender, EventArgs e)
{ // update the control (progress bar) here }

Main Point: Now when you try to access your windows control in the WorkerMethod or the event handler, you get the following exception:

Cross-thread operation not valid: Control ‘progressBar’ accessed from a thread other than the thread it was created on.

Without talking about the what and why, here is how to get to your control:

progressBar.Invoke(new MethodInvoker(
delegate { progressBar.Increment(); }));

Mahdieh

Two Little Problems

Tuesday, February 5th, 2008

Two little problems that you may encounter in a Windows Application project:

1- You are using a DataGridView and want to change some (all) rows’ (cells) style, for example their color. Setting the Style property of rows or cells is the way to do so, but it won’t change anything unless done in dataGridView_RowsAdded event handler - at least I couldn’t find any other way to make it work.

2- You have a TabControl and usually want to make TabPages closable (using a ContextMenu)
and ,of course, don’t want the context menu to open inside the client area of the tab page, but just on the small header rectangle, as in VisualStudio tab pages.

Solution: ContextMenu has an Opening event and TabControl has a MouseDown event which fires before the ‘Opening’ event, so you’re gonna use them to cancel the opening whenever the click is not in the right place. Obviously, you should use a private bool allowContextMenuOpening.

private void tabControlPrograms_MouseDown(object sender, MouseEventArgs e)
{
   if (e.Button == MouseButtons.Right)
      for (int i = 0; i < tabControlPrograms.TabCount; i++)
         if (tabControlPrograms.GetTabRect(i).Contains(e.Location))
         {
            allowContextMenuOpening = true;
            return;
         }
}

private void closeVisitorContextMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
{
   if (!allowContextMenuOpening)
      e.Cancel = true;
   else
      allowContextMenuOpening = false;
}

Mahdieh