按任务调用异步操作

时间:2017-07-12 07:20:04

标签: c# asp.net wcf asynchronous callback

我有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:此时无法启动异步操作。异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的某些事件中启动。如果在执行页面时发生此异常,请确保将页面标记为&lt;%@ Page Async =“true”%&gt;。此异常还可能表示尝试调用“异步void”方法,该方法通常在ASP.NET请求处理中不受支持。相反,异步方法应该返回一个Task,调用者应该等待它。

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

提前致谢。

1 个答案:

答案 0 :(得分:0)

我不知道为什么我不能在客户端使用无限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管道中一个无限的任务是不可接受的,因为引擎应该知道一个任务最终会被超时结束....