Recently, I developed some business objects that I needed to use both in WPF world (with vanilla data binding), as well as within a WCF web service. Of course, from the WPF books we learn that a DependenyProperty can only be directly accessed from the thread where it was created. So the implementation does that in the appropriate thread. The problem I still had was that my messages were dispatched to my business object, but that they remained in the queue with a DispatcherOperationStatus Pending. Thanks to the guys from the WPF team (Dwayne Need and a bunch of other folks) and their "did you actually start the Dispatcher?" question, here's a small sample. Maybe it helps ...
Christian
namespace Microsoft.EMIC.ChGeuer.BlogSample
{
using System;
using System.Windows;
using System.Threading;
using System.Windows.Threading;
using System.Diagnostics;
public class HostingDependencyObjectInOwnApplicationRepro
[STAThread]
static void Main(string[] args)
Thread.CurrentThread.Name = "MyServiceHostApplication";
Dispatcher d = Dispatcher.CurrentDispatcher;
SomeDataObject data = new SomeDataObject() { Id = "Foo" };
data.DataChanged += new DataChangedEventHandler(ProgramDataChanged);
Console.WriteLine(data.DoStuff("New value 1"));
new Thread((ThreadStart)delegate()
// This is the thread that ocntinuously works with the data,
// like a WCF service
Thread.CurrentThread.Name = "MyWCFService";
for (var i = 0; i < 10; i++)
Thread.Sleep(500);
var res = data.DoStuff(string.Format("New value {0}", i));
if (res == null)
break;
}
Console.WriteLine("The result from the thread is '{0}'", res);
}).Start();
Dispatcher mainDispatcher = Dispatcher.CurrentDispatcher;
Console.WriteLine("Press <Return> to close the application");
Console.ReadLine();
AppShutdownDispatcher(mainDispatcher);
Dispatcher.Run();
public static void AppShutdownDispatcher(Dispatcher theMainDispatcher)
if (theMainDispatcher.CheckAccess())
theMainDispatcher.InvokeShutdown();
else
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Send, (Action)(() =>
}));
static void ProgramDataChanged(object sender, DataChangedEventArgs e)
Console.WriteLine("Data changed to {0}", e.NewValue);
public delegate void DataChangedEventHandler(object sender, DataChangedEventArgs e);
public class DataChangedEventArgs : EventArgs
internal DataChangedEventArgs(string newValue)
this.NewValue = newValue;
public string NewValue { get; private set; }
public class SomeDataObject : DependencyObject
public SomeDataObject()
this.Dispatcher.Hooks.OperationPosted += new DispatcherHookEventHandler(DispatcherOperationPosted);
public event DataChangedEventHandler DataChanged;
public static readonly DependencyProperty IdProperty =
DependencyProperty.Register("Id", typeof(string), typeof(SomeDataObject),
new PropertyMetadata() { DefaultValue = string.Empty, PropertyChangedCallback = OnDataChanged });
public string Id
get { return (string)this.GetValue(SomeDataObject.IdProperty); }
set { this.SetValue(SomeDataObject.IdProperty, value); }
private static void OnDataChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
Debug.Assert(sender is SomeDataObject);
DataChangedEventHandler handler = ((SomeDataObject)sender).DataChanged;
if (handler != null)
handler(sender, new DataChangedEventArgs((string)e.NewValue));
private void DispatcherOperationPosted(object sender, DispatcherHookEventArgs e)
Console.Out.WriteLine("Posted operation with prio {0}", e.Operation.Priority.ToString());
e.Dispatcher.UnhandledException += new DispatcherUnhandledExceptionEventHandler(Dispatcher_UnhandledException);
void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
Console.Error.WriteLine("Unhandled {0}", e.Exception.GetType().Name);
public string DoStuff(string someNewValue)
Console.WriteLine("Called by {0}", Thread.CurrentThread.Name);
if (this.Dispatcher.HasShutdownStarted)
return null;
if (this.Dispatcher.CheckAccess())
this.Id = someNewValue;
return this.Id + " computed";
Func<string, string> doIt = (arg) =>
this.Id = arg;
};
// return (string)this.Dispatcher.Invoke(DispatcherPriority.Send,
// TimeSpan.FromMilliseconds(500), doIt, someNewValue);
DispatcherOperation op = base.Dispatcher.BeginInvoke(DispatcherPriority.Send, doIt, someNewValue);
var status = op.Wait(TimeSpan.FromMilliseconds(500));
Console.WriteLine("Status: " + status.ToString());
if (status == DispatcherOperationStatus.Completed)
return (string)op.Result;
else if (status == DispatcherOperationStatus.Aborted)
return "Cancelling";
throw new Exception("Houston, we have a problem");