Silverlight 一次只能同时发送一定数量的 WCF 请求。我正在尝试序列化我的应用程序的特定部分正在执行的请求,因为我不需要它们同时运行。
问题如下(总结如下):
“Silverlight 应用程序中的 WCF 代理使用启动 Web 服务调用的线程的 SynchronizationContext 来安排在收到响应时调用异步事件处理程序。当从 Silverlight 应用程序的 UI 线程启动 Web 服务调用时,异步事件处理程序代码也将在 UI 线程上执行。”
http://tomasz.janczuk.org/2009/08/improving-performance-of-concurrent-wcf.html
摘要:基本上,如果您阻塞调用异步方法的线程,它将永远不会被调用。
我无法找出正确的线程模型,这将以合理的方式给我想要的东西。
我唯一的其他要求是我不希望 UI 线程阻塞。
据我所见,如果 UI 线程有一个工作线程将调用排队为 Action
,那么应该怎么做?代表,然后使用 AutoResetEvent
在另一个工作线程中一次执行一个任务。有两个问题:
1)调用 async 的线程不能阻塞,因为那样 async 永远不会被调用。实际上,如果您将该线程放入等待循环中,我注意到它也不会被调用
2)您需要一种方法来从异步调用的完成方法发出信号,表明它已完成。
抱歉说了这么久,感谢阅读。有任何想法吗?
最佳答案
我使用了一个我自己构建的类来同步执行加载操作。使用该类,您可以注册不同域上下文的多个加载操作,然后一一执行。当所有操作完成(成功或失败)时,您可以向被调用的类的构造函数提供一个 Action。
这是类的代码。我认为它不完整,您必须对其进行更改以符合您的期望。也许它可以在你的情况下帮助你。
public class DomainContextQueryLoader {
private List<LoadOperation> _failedOperations;
private Action<DomainContextQueryLoader> _completeAction;
private List<QueuedQuery> _pendingQueries = new List<QueuedQuery>();
public DomainContextQueryLoader(Action<DomainContextQueryLoader> completeAction) {
if (completeAction == null) {
throw new ArgumentNullException("completeAction", "completeAction is null.");
}
this._completeAction = completeAction;
}
/// <summary>
/// Expose the count of failed operations
/// </summary>
public int FailedOperationCount {
get {
if (_failedOperations == null) {
return 0;
}
return _failedOperations.Count;
}
}
/// <summary>
/// Expose an enumerator for all of the failed operations
/// </summary>
public IList<LoadOperation> FailedOperations {
get {
if (_failedOperations == null) {
_failedOperations = new List<LoadOperation>();
}
return _failedOperations;
}
}
public IEnumerable<QueuedQuery> QueuedQueries {
get {
return _pendingQueries;
}
}
public bool IsExecuting {
get;
private set;
}
public void EnqueueQuery<T>(DomainContext context, EntityQuery<T> query) where T : Entity {
if (IsExecuting) {
throw new InvalidOperationException("Query cannot be queued, cause execution of queries is in progress");
}
var loadBatch = new QueuedQuery() {
Callback = null,
Context = context,
Query = query,
LoadOption = LoadBehavior.KeepCurrent,
UserState = null
};
_pendingQueries.Add(loadBatch);
}
public void ExecuteQueries() {
if (IsExecuting) {
throw new InvalidOperationException("Executing of queries is in progress");
}
if (_pendingQueries.Count == 0) {
throw new InvalidOperationException("No queries are queued to execute");
}
IsExecuting = true;
var query = DequeueQuery();
ExecuteQuery(query);
}
private void ExecuteQuery(QueuedQuery query) {
System.Diagnostics.Debug.WriteLine("Load data {0}", query.Query.EntityType);
var loadOperation = query.Load();
loadOperation.Completed += new EventHandler(OnOperationCompleted);
}
private QueuedQuery DequeueQuery() {
var query = _pendingQueries[0];
_pendingQueries.RemoveAt(0);
return query;
}
private void OnOperationCompleted(object sender, EventArgs e) {
LoadOperation loadOperation = sender as LoadOperation;
loadOperation.Completed -= new EventHandler(OnOperationCompleted);
if (loadOperation.HasError) {
FailedOperations.Add(loadOperation);
}
if (_pendingQueries.Count > 0) {
var query = DequeueQuery();
ExecuteQuery(query);
}
else {
IsExecuting = false;
System.Diagnostics.Debug.WriteLine("All data loaded");
if (_completeAction != null) {
_completeAction(this);
_completeAction = null;
}
}
}
}
更新:
我刚刚注意到您没有使用 WCF RIA 服务,所以这门课可能对您没有帮助。
关于multithreading - Silverlight - 一次将应用程序限制为一个 WCF 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6829461/