Click here to Skip to main content
15,067,335 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
hi all!

I have made user control (could say it is pretty much like button). My control offers typical click event and also custom press event when user has pressed my control atleast 2 seconds (in this case click event is not sent). Press event is determinated by using timer elapsed event.

The problem is that when using my control i can access my sender in click event but in press event i got error "The calling thread cannot access this object because a different thread owns it." Im confused..

Here is codesnippet from my customcontrol

C#
//timerstarts when user presses button, after 2 seconds this will be launced.     
private void aTimer_Elapsed(object source, ElapsedEventArgs e)
{
aTimer.Stop();
OnPressEvent();           
}

//my Press event               
public event EventHandler<eventargs> PressEvent;

private void OnPressEvent()
{
     IsPressEventLaunced = true; //this flag prevents click event to be send

     // Copy to a temporary variable to be thread-safe.
     EventHandler<eventargs> temp = PressEvent;
          
   if (temp != null)
   {          
    temp(this, new EventArgs()); //The problem!! I can send 'this' BUT in client side cannnot use 'sender'
   }
}

//my click event
public event RoutedEventHandler Click;


//happens when mouse is released, sends click event unless pressevent is launched
private void myControl_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{        
aTimer.Stop();
           

if (!IsPressEventLaunced)
    {
     if (null != Click)
        Click(sender, e);
    }
}</eventargs></eventargs>


And here is snippet from client side

C#
private void button_PressEvent(object sender, EventArgs e)
        {
            myControl temp = (myControl )sender as myControl ;
            //Here I cannot use sender information
        }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            myControl temp = (myControl )sender as myControl;
            //Here I can access sender information
        }


hope you got idea :)
Posted

All access to WPF controls must be done on the UI thread, so your OnPressEvent should look something like this

C#
private void OnPressEvent()
{
     if(!Dispatcher.CheckAccess())
     {
          Dispatcher.Invoke((Action) OnPressEvent, null);
          return;
     }

     IsPressEventLaunced = true; //this flag prevents click event to be send

     // Copy to a temporary variable to be thread-safe.
     EventHandler<eventargs> temp = PressEvent;

   if (temp != null)
   {
    temp(this, new EventArgs()); //The problem!! I can send 'this' BUT in client side cannnot use 'sender'
   }
}
   
Comments
paleGegg0 15-Aug-11 3:28am
   
Thanks a lot, your snippet seems to do the trick! I have to do some research about ui threads to learn more about it :)
Just to help you a bit in your research in threading and invocation mechanism:

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

Invocation puts all the data needed for a call (it includes delegate instance, reference to the instance of the delegate method (null for static methods) and method parameter values) in some queue and the UI thread uses this queue for actual calls.

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

—SA
   
v2
Comments
paleGegg0 15-Aug-11 23:55pm
   
Thanks a lot! It is nice to see that someone reads solved questions and gives more feedback. Have a nice day SAKryokov :)
   
You're very welcome.
If you agree it makes sense, please formally accept this solution; you can accept more than one -- thank you.
Good luck, call again.
--SA
paleGegg0 16-Aug-11 1:36am
   
Oh sorry, did not know that I can accept more than one solution. Your solution is accepted!
   
Thank you.
Good luck,
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900