To ensure thread safety where Invoke is not implemented, can be done with a System.Windows.Threading.Dispatcher.

 

The Dispatcher should of course run on same thread as the thread safe instance, hence the Dispatcher instance should be created when the thread safe instance is constructed.

 

A little example is in order here, I guess.

Say that we have a object Foo accessed by object Bar, in Bar’ backgroundworker. This would cause a cross-thread exception

public class Foo
{
    private Object _fooBar;
    public Object FooBar
    {
        get { return _fooBar; }
        set { _fooBar = value; }
    }
    
    public Foo()
    {
    }
}

public class Bar
{
    private Foo _foo;
    public Foo Foo
    {
        get { return _foo; }
        set { _foo = value; }
    }
    
    public Bar()
    {
        this.Foo = new Foo();

        BackgroundWorker backgroundWorker = new BackgroundWorker();
        backgroundWorker.DoWork += backgroundWorker_DoWork;
    }

    void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        Foo.FooBar = NextFooBar();
    }

    private object NextFooBar()
    {
        return new Object();
    }
}

Since Foo don’t implement Invoke (or inherit from a object that does), one way to get about this would be to use a System.Windows.Threading.Dispatcher.

public class Foo
{
    private System.Windows.Threading.Dispatcher _dispatcher = null;
    private Object _fooBar;
    public Object FooBar
    {
        get { return _fooBar; }
        set { _dispatcher.Invoke(((Action<Object>))delegate(v) { internalSetFooBar(v); }, new object[] { value }); }
    }
    private void internalSetFooBar(object value)
    {
        _fooBar = value;
    }
    
    public Foo()
    {
        _dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher;
    }
}

public class Bar
{
    private Foo _foo;
    public Foo Foo
    {
        get { return _foo; }
        set { _foo = value; }
    }
    
    public Bar()
    {
        this.Foo = new Foo();

        BackgroundWorker backgroundWorker = new BackgroundWorker();
        backgroundWorker.DoWork += backgroundWorker_DoWork;
    }

    void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        Foo.FooBar = NextFooBar();
    }

    private object NextFooBar()
    {
        return new Object();
    }
}

As always, feel free to comment, or ask.

 


Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading