【问题标题】:call asynchronous operation by task按任务调用异步操作
【发布时间】:2017-12-16 11:37:02
【问题描述】:

我有 Duplex 和 Sessionfull 服务和一个操作:

public FindStudies_DTO_OUT FindStudies(FindStudies_DTO_IN findStudies_DTO_IN)
    {
        var token = Token;
        List<Study_C> ret = new List<Study_C>();
        _dispatcherCallBack = OperationContext.Current.GetCallbackChannel<IDispatcherCallBack>();
        AnnuncedFindStudies += DispatcherService_AnnuncedFindStudies;
        AnnuncedSPError += DispatcherService_AnnuncedSPError;
        Parallel.ForEach(Cluster, sp =>
        {
            //Blah blah
            OnAnnuncedSPError(new SPError_DTO()
            {
                ServicePointName = sp.Name,
                ErrorMessage = "Ping failed for " + sp.Name
            });
            var result = new List<Study_C>();//Filled
            lock (ret)
            {
                OnAnnounceFindStudies(new FindStudies_DTO()
                {
                    ServicePointName = sp.Name,
                    Studies = result
                });
                ret.AddRange(result);
            }
            //blah blah
        });
        return new FindStudies_DTO_OUT(ret.Sort(findStudies_DTO_IN.SortColumnName, findStudies_DTO_IN.SortOrderBy));
    }

和在消费者端(通用处理程序中的 Web 应用程序):

var findTask = Task.Factory.StartNew(() =>
                    {
                        DispatcherClient dispatcherClient = new DispatcherClient(new DispatcherCallBack(), "dispatcherEndPoint", Token, Global.Cluster);
                        dispatcherClient.AnnuncedSPError += DispatcherClient_AnnuncedSPError;
                        dispatcherClient.AnnuncedFindStudies += DispatcherClient_AnnuncedFindStudies;
                        var res = dispatcherClient.FindStudies(new FindStudies_DTO_IN(startIndex, numberOfRows, col.FromText(sortColumnName), sort.FromText(sortOrder), criteria, searchMatching));
                        studies = Studies;
                    });
                    findTask .Wait();

在客户端,当我在 var findTask 上设置断点时,一切正常,但是当我删除断点时,它只在第一次运行时就可以工作,但之后我得到以下异常:

InvalidOperationException:此时无法启动异步操作。异步操作只能在异步处理程序或模块内或在页面生命周期中的某些事件期间启动。如果在执行页面时发生此异常,请确保将页面标记为 。此异常还可能表示尝试调用“async void”方法,在 ASP.NET 请求处理中通常不支持该方法。相反,异步方法应该返回一个 Task,调用者应该等待它。

有人知道客户端应该如何实现吗?

提前致谢。

【问题讨论】:

    标签: c# asp.net wcf asynchronous callback


    【解决方案1】:

    我不知道为什么我不能在客户端使用无限 wait,但从我读过的 here 来看,建议不要在同步上使用 asyc,反之亦然。

    无论如何我已经通过以下解决方案解决了这个问题:

    在服务器端运行一个任务并在其中处理一些事件:

    public FindStudies_DTO_OUT FindStudies(FindStudies_DTO_IN findStudies_DTO_IN)
        {
            var token = Token;
            List<Study_C> ret = new List<Study_C>();
            _dispatcherCallBack = OperationContext.Current.GetCallbackChannel<IDispatcherCallBack>();
            AnnuncedFindStudies += (s, e) =>
            {
                _dispatcherCallBack.OnAnnounceFindStudies(e);
            };
            AnnuncedSPError += (s, e) =>
            {
                _dispatcherCallBack.OnAnnunceSPError(e);
            };
            AnnuncedComplete += (s, e) =>
            {
                _dispatcherCallBack.OnAnnunceComplete();
            };
            Task.Run(() =>
            {
                //Blah blah
                if (proxyGetError)
                    OnAnnuncedSPError(new SPError_DTO()
                    {
                        ServicePointName = sp.Name,
                        ErrorMessage = "Ping failed for " + sp.Name
                    });
                var result = new List<Study_C>();//Filled
                lock (ret)
                {
                    OnAnnounceFindStudies(new FindStudies_DTO()
                    {
                        ServicePointName = sp.Name,
                        Studies = result
                    }); 
                }
                //blah blah
                OnAnnounceComplete();
            });
            return new FindStudies_DTO_OUT();
        }
    

    在消费者端,任务也会在超时的情况下运行,并在AnnuncedComplete 被提升时完成:

     DispatcherClient dispatcherClient = new DispatcherClient(new DispatcherCallBack(), "dispatcherEndPoint", Token, Global.Cluster);
                        Task.Run(() =>
                        {
                            studies = new List<Study_C>();
                            try
                            {
                                ManualResetEvent ev = new ManualResetEvent(false);
                                dispatcherClient.AnnuncedSPError += (s, e) =>
                                {
                                    spErrorMessage += e.ServicePointName + "<br/>";
                                };
                                dispatcherClient.AnnuncedFindStudies += (s, e) =>
                                { 
                                    lock (studies)
                                    {
                                        studies.AddRange(e.Studies);
                                    }
                                };
                                dispatcherClient.AnnuncedComplete += (s, e) =>
                                {
                                    ev.Set();
                                };
                                var rrr = dispatcherClient.FindStudies(new FindStudies_DTO_IN(startIndex, numberOfRows, col.FromText(sortColumnName), sort.FromText(sortOrder), criteria, searchMatching)).Studies;
                                ev.WaitOne();
                            }
                            catch (Exception exp)
                            {
                                Logging.Log(LoggingMode.Error, "Failed to Find Studies by Dispatcher, EXP:{0}", exp);
                            }
                        }).Wait(dispatcherClient.Endpoint.Binding.ReceiveTimeout);
    

    主要问题是findTask.Wait() 没有毫秒超时 但是通过为任务设置毫秒超时,一切都很好。

    我认为在 ASP.Net 管道中,无限任务是不可接受的,因为这个原因引擎应该知道任务最终会因超时而结束......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多