这个我要试一试...
您可以查看其 CodePlex 站点上的 MVVM-Light 源代码。我将在此处粘贴相关方法(为了这篇文章而略加注释):
private void SendToTargetOrType<TMessage>(TMessage message, Type messageTargetType, object token)
{
var messageType = typeof(TMessage);
if (_recipientsOfSubclassesAction != null)
{
// Clone to protect from people registering in a "receive message" method
// Correction Messaging BL0008.002
var listClone =
_recipientsOfSubclassesAction.Keys.Take(_recipientsOfSubclassesAction.Count()).ToList();
foreach (var type in listClone)
{
List<WeakActionAndToken> list = null;
if (messageType == type
|| messageType.IsSubclassOf(type)
|| type.IsAssignableFrom(messageType))
{
lock (_recipientsOfSubclassesAction)
{
list = _recipientsOfSubclassesAction[type].Take(_recipientsOfSubclassesAction[type].Count()).ToList();
}
}
// Class A probably sends a message here from the UI thread
SendToList(message, list, messageTargetType, token);
}
}
if (_recipientsStrictAction != null)
{
// Class B grabs this lock on the background thread.
// Class A continues processing on the UI thread and arrives here.
// An attempt is made to grab the lock on the UI thread but it is
// blocked by the background thread & Class B which in turn is waiting
// on the UI thread. And here you have yourself a deadlock
lock (_recipientsStrictAction)
{
if (_recipientsStrictAction.ContainsKey(messageType))
{
var list = _recipientsStrictAction[messageType]
.Take(_recipientsStrictAction[messageType].Count())
.ToList();
// Class B sends its message here.
// Class C receives the message and does an Invoke on the UI thread
SendToList(message, list, messageTargetType, token);
}
}
}
RequestCleanup();
}
- A 类可能会在“子类接收者”接收的 UI 线程上发送一条消息。
- B 类是接收此消息并启动您的后台任务的收件人。
- 然后,您的后台任务会发送一条消息,其中包含“严格操作收件人”。
- B 类在后台线程上获取“_recipientsStrictAction”锁。
- B 类将消息发送到 C 类,C 类在 UI 线程上执行调用。
- 此调用阻塞,因为 UI 线程仍在执行第一条消息。
- UI 线程继续执行,然后尝试获取 UI 线程上的“_recipientsStrictAction”锁。不幸的是,您的后台线程(正在等待 UI 线程)已经获得了锁。你现在陷入僵局:(
可能要考虑在 C 类中执行 InvokeAsync 而不是 Invoke。我认为您可能可以通过这种方式避免这个问题。
让我想知道为什么 MVVM 灯会在锁的“内部”发送消息。似乎是一件不那么酷的事情。输入完所有这些后,我环顾了 CodePlex 网站,看起来这个问题已记录在案:
http: //mvvmlight.codeplex.com/workitem/7581