Andreas
Andreas

Reputation: 1081

Delayed firing of custom event

I want to extend the TextBox control, so it will fire a custom event with a specified delay.

Here is the code i have so far:

    public class DelayTextBox : TextBox
{
    private Timer _delayTimer;
    private int _threshold = 1000;

    public DelayTextBox()
    {
        _delayTimer = new Timer(_threshold);
        _delayTimer.Elapsed += new ElapsedEventHandler(_delayTimer_Elapsed);
    }

    public int Delay
    {
        set { _threshold = value; }
    }

    private void _delayTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        _delayTimer.Stop();
        RaiseDelayedTextChangedEvent();
    }

    protected override void OnTextChanged(TextChangedEventArgs e)
    {
        _delayTimer.Stop();
        _delayTimer.Start();
    }

    private static readonly RoutedEvent DelayedTextChangedEvent = EventManager.RegisterRoutedEvent(
    "DelayedTextChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DelayTextBox));

    public event RoutedEventHandler DelayedTextChanged
    {
        add { AddHandler(DelayedTextChangedEvent, value); }
        remove { RemoveHandler(DelayedTextChangedEvent, value); }
    }

    private void RaiseDelayedTextChangedEvent()
    {
        RoutedEventArgs newEventArgs = new RoutedEventArgs(DelayTextBox.DelayedTextChangedEvent);
        RaiseEvent(newEventArgs);
    }
}

The problem is that whenever i fire RaiseDelayedTextChangedEvent(), i get an exception, telling me

'The calling thread cannot access this object because a different thread owns it.'

The exception is thrown here:

private void RaiseDelayedTextChangedEvent()
    {
        RoutedEventArgs newEventArgs = new RoutedEventArgs(DelayTextBox.DelayedTextChangedEvent);
        RaiseEvent(newEventArgs);
    } <---- Here

Upvotes: 0

Views: 1500

Answers (2)

K Mehta
K Mehta

Reputation: 10533

That's because the Timer runs in a different thread, and UI cannot be modified from that thread (like your exception says). Try using a DispatcherTimer instead. You can learn more about it here: http://code.dortikum.net/2008/08/06/timer-vs-dispatchertimer-in-wpf/

Upvotes: 2

Leonard Br&#252;nings
Leonard Br&#252;nings

Reputation: 13222

You need to use the dispatcher to raise the event in the STA Thread.

This article explains the threading issues you are having http://www.switchonthecode.com/tutorials/working-with-the-wpf-dispatcher

private void RaiseDelayedTextChangedEvent()
    {
        RoutedEventArgs newEventArgs = new RoutedEventArgs(DelayTextBox.DelayedTextChangedEvent);

        this.Dispatcher.BeginInvoke(
                System.Windows.Threading.DispatcherPriority.Normal,
                (UpdateTheUI)delegate(RoutedEventArgs eArgs)
                {
                   RaiseEvent(eArgs);
                }, newEventArgs );

    }

Upvotes: 0

Related Questions