如何在Silverlight BackgroundWorker中运行批处理的WCF服务调用

时间:2010-03-17 20:02:39

标签: silverlight backgroundworker

是否有任何现有管道在BackgroundWorker中批量运行WCF调用?

显然,因为所有Silverlight WCF调用都是异步的 - 如果我在后台工作中运行它们,它们都将立即返回。

如果这是一种运行服务调用并收集结果的好方法,我只是不想实施讨厌的黑客攻击。

  • 无论在
  • 中完成了什么顺序
  • 所有操作都是独立的
  • 我希望一次运行的项目不超过5件

编辑:我也注意到(当使用Fiddler时)任何时候都不能发送大约7个电话。即使在浏览器外运行时,此限制也适用。这是由于我的默认浏览器设置 - 还是可配置的。显然它是一个穷人的解决方案(并不适合我想要的)但我可能需要考虑的事情,以确保我的应用程序的其余部分保持响应,如果我将此作为后台任务运行而不是希望它耗尽我所有的关系。

1 个答案:

答案 0 :(得分:9)

我认为最好的办法是让主线程将服务请求项放入与BackgroundWorker线程共享的队列中。然后,BackgroundWorker可以从队列中读取,当它检测到新项目时,启动异步WCF服务请求,并设置为处理AsyncCompletion事件。在从不同的线程调用Enqueue()或Dequeue()之前,不要忘记锁定队列。

以下是一些建议解决方案开始的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace MyApplication
{
    public class RequestItem
    {
        public string RequestItemData { get; set; }
    }

    public class ServiceHelper
    {
        private BackgroundWorker _Worker = new BackgroundWorker();
        private Queue<RequestItem> _Queue = new Queue<RequestItem>();
        private List<RequestItem> _ActiveRequests = new List<RequestItem>();
        private const int _MaxRequests = 3;

        public ServiceHelper()
        {
            _Worker.DoWork += DoWork;
            _Worker.RunWorkerAsync();
        }

        private void DoWork(object sender, DoWorkEventArgs e)
        {
            while (!_Worker.CancellationPending)
            {
                // TBD: Add a N millisecond timer here
                //      so we are not constantly checking the Queue

                // Don't bother checking the queue
                // if we already have MaxRequests in process
                int _NumRequests = 0;
                lock (_ActiveRequests)
                {
                    _NumRequests = _ActiveRequests.Count;
                }
                if (_NumRequests >= _MaxRequests)
                    continue;

                // Check the queue for new request items
                RequestItem item = null;
                lock (_Queue)
                {
                    RequestItem item = _Queue.Dequeue();
                }
                if (item == null)
                    continue;

                // We found a new request item!
                lock (_ActiveRequests)
                {
                    _ActiveRequests.Add(item);
                }

                // TBD: Initiate an async service request,
                //      something like the following:
                try
                {
                    MyServiceRequestClient proxy = new MyServiceRequestClient();
                    proxy.RequestCompleted += OnRequestCompleted;
                    proxy.RequestAsync(item);
                }
                catch (Exception ex)
                {
                }
            }
        }

        private void OnRequestCompleted(object sender, RequestCompletedEventArgs e)
        {
            try
            {
                if (e.Error != null || e.Cancelled)
                    return;

                RequestItem item = e.Result;

                lock (_ActiveRequests)
                {
                    _ActiveRequests.Remove(item);
                }
            }
            catch (Exception ex)
            {
            }
        }

        public void AddRequest(RequestItem item)
        {
            lock (_Queue)
            {
                _Queue.Enqueue(item);
            }
        }
    }
}

如果我能提供更多帮助,请告诉我。