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.