如何在 Silverlight BackgroundWorker 中运行批量 WCF 服务调用

发布于 2024-08-25 23:11:29 字数 558 浏览 5 评论 0原文

是否有任何现有管道可以在 后台工作人员

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

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

  • 不管它们以什么顺序完成
  • 所有操作都是独立的
  • 我希望同时运行不超过 5 个项目

编辑:我还注意到(使用 Fiddler 时)不超过大约一次可以发送 7 个呼叫。即使在浏览器外运行时,此限制也适用。这是由于我的默认浏览器设置造成的 - 或者也可以配置。显然,这是一个穷人的解决方案(并且不适合我想要的),但如果我将其作为后台任务运行并且不这样做,我可能需要考虑一些事情,以确保我的应用程序的其余部分保持响应希望它用完我所有的连接。

Is there any existing plumbing to run WCF calls in batches in a BackgroundWorker?

Obviously since all Silverlight WCF calls are async - if I run them all in a backgroundworker they will all return instantly.

I just don't want to implement a nasty hack if theres a nice way to run service calls and collect the results.

  • Doesnt matter what order they are done in
  • All operations are independent
  • I'd like to have no more than 5 items running at once

Edit: i've also noticed (when using Fiddler) that no more than about 7 calls are able to be sent at any one time. Even when running out-of-browser this limit applies. Is this due to my default browser settings - or configurable also. obviously its a poor man's solution (and not suitable for what i want) but something I'll probably need to take account of to make sure the rest of my app remains responsive if i'm running this as a background task and don't want it using up all my connections.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦一生花开无言 2024-09-01 23:11:29

我认为最好的选择是让主线程将服务请求项放入与 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);
            }
        }
    }
}

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

I think your best bet would be to have your main thread put service request items into a Queue that is shared with a BackgroundWorker thread. The BackgroundWorker can then read from the Queue, and when it detects a new item, initiate the async WCF service request, and setup to handle the AsyncCompletion event. Don't forget to lock the Queue before you call Enqueue() or Dequeue() from different threads.

Here is some code that suggests the beginning of a solution:

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);
            }
        }
    }
}

Let me know if I can offer more help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文