使用异步WCF服务的CCR [英] Using the CCR with ASynchronous WCF Service

查看:131
本文介绍了使用异步WCF服务的CCR的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习如何结合一个异步WCF Web服务使用CCR(并发与协调运行时)。

这是测试WCF服务:

 公共类服务:IService
    {
        私人Accounts.Manager的AccountManager =新Accounts.Manager();
        公众的IAsyncResult BeginGetAccount(INT ID,AsyncCallback的回调,对象的状态)
        {
            //我如何调用该函数CCR不会阻塞线程?
            抛出新NotImplementedException();
        }        公共字符串EndGetAccount(IAsyncResult的结果)
        {
            //我如何完成呼叫和回传,结果呢?
            抛出新NotImplementedException();
        }
    }

这将需要一个ID号,并返回匹配的帐户名(如果有的话)

我已经写了(S)一CCR函数应该找到匹配的帐户
(显然需要大量的工作 - 这是概念恰恰证明)
这里是我来脱胶。

我如何传回的结果(全球端口?)
更重要的是:我如何堵塞CCR到WCF异步服务呼叫而不阻塞线程

 公众的IEnumerator< ITask>是getAccount(INT ID)
    {
        SqlDataReader的读卡器= NULL;
        SqlConnection的连接=新的SqlConnection(@数据源= \\ SQLEX $ P $干燥综合征;初始目录= BizData;集成安全性= TRUE;异步=真;);
        查询字符串=SELECT * FROM帐户,帐户ID = @AccountID;
        的SqlCommand命令=新的SqlCommand(查询,连接);
        SqlParameter的帐户ID =新的SqlParameter(帐户ID,身份证);
        command.Parameters.Add(帐户);        connection.Open();
        产量返回Arbiter.Choice(SQLAdapter.GetReader(命令),
            委托(SqlDataReader的R){读卡器= R; },
            委托(例外五){Console.Write(无法获得SQL数据); });        如果(读者== NULL)产量突破;        而(reader.Read())
        {
            帐户帐户=新帐户{ID = Convert.ToInt32(读卡器[帐户ID])
                NAME =读卡器[帐户]。的ToString()
                ParkingNo = Convert.ToInt32(读卡器[ParkingNo])
                密码读卡器= [密码]的ToString()}。
            //邮政帐户?
        }
        connection.close()时;
    }


解决方案

好吧,我终于得到了地方与这一切!

首先是:你需要一个定制的AsyncResult类

 类AsyncResult:IAsyncResult的,IDisposable接口
    {
        对象_state;
        ManualResetEvent的_waitHandle =新的ManualResetEvent(假);
        布尔_isCompleted;        #区域IAsyncResult的成员
        公共对象AsyncState
        {
            {返回_state; }
        }        公共System.Threading.WaitHandle AsyncWaitHandle
        {
            {返回_waitHandle; }
        }        公共BOOL CompletedSynchronously
        {
            获得{返回false; }
        }        公共BOOL IsCompleted
        {
            {返回_isCompleted; }
        }
        #endregion        异常_exception;
        内部异常异常
        {
            {返回_exception; }
        }        Accounts.Account _result;
        内部Accounts.Account结果
        {
            {返回_result; }
        }        内部AsyncResult(端口集< Accounts.Account,异常>港口,DispatcherQueue队列,AsyncCallback的回调,对象的状态)
        {
            _state =状态;            Arbiter.Activate(队列,
                Arbiter.Choice(端口,
                    R =>
                    {
                        _result = R;
                        完成(回调);
                    },
                    E =>
                    {
                        _exception = E;
                        完成(回调);
                    }
                )
            );
        }        私人无效完成(AsyncCallback的回调)
        {
            _isCompleted = TRUE;
            _waitHandle.Set();            如果(回调!= NULL)
            {
                ThreadPool.QueueUserWorkItem(S = GT;的回调(本));
            }
        }        私人布尔disposedValue = FALSE;        公共无效的Dispose()
        {
            如果(!this.disposedValue)
            {
                _waitHandle.Close();
                _waitHandle = NULL;
                _state = NULL;
            }
            this.disposedValue =真;
        }
    }

好吧,那么我们就需要用异步WCF方法来把这些在呼叫:

 公共类服务:IService
    {
        私人调度调度;
        私人DispatcherQueue DQ;        公共服务()
        {
             调度员=新的调度程序();
             DQ =新DispatcherQueue(CCR DispatcherQueue,调度员);
        }        公众的IAsyncResult BeginGetAccount(INT ID,AsyncCallback的回调,对象的状态)
        {
            端口集< Accounts.Account,异常>端口=新的端口集< Accounts.Account,异常>();
            Accounts.Manager经理=新Accounts.Manager();
            manager.GetAccountData(DQ,端口号);            AsyncResult结果=新AsyncResult(端口,DQ,回调状态);
            返回结果;
        }        公共字符串EndGetAccount(IAsyncResult的结果)
        {
            {
                VAR帐户名=的String.Empty;
                如果((结果!= NULL))
                {
                    使用(Common.AsyncResult asyncResult =为Common.AsyncResult结果)
                    {                        如果(asyncResult == NULL)
                        {
                            抛出新的NullReferenceException(IAsynchResult参数为空);
                        }                        asyncResult.AsyncWaitHandle.WaitOne();
                        如果(asyncResult.Result!= NULL)
                        {
                            帐户名= asyncResult.Result.Name;
                        }
                    }
                }
                返回帐户名;
            }
        }
    }

然后你只需要IEnumerator的方法,答案张贴到端口

I'm learning how to use the CCR (Concurrency and Coordination Runtime) in conjunction with a Asynchronous WCF Web Service.

This is the Test WCF Service:

    public class Service : IService
    {
        private Accounts.Manager accountManager = new Accounts.Manager();
        public IAsyncResult BeginGetAccount(int id, AsyncCallback callback, object state)
        {
            //How Do I Call the CCR Function without blocking a Thread?
            throw new NotImplementedException();
        }

        public string EndGetAccount(IAsyncResult result)
        {
            //How Do I Finish the Call and Pass back the Result?
            throw new NotImplementedException();
        }
    }

It will take a ID number and return the Matching Account Name (if Any)

I have written a CCR function that should find the matching account(s) (obviously needs a lot of work - this is just proof of concept) Here is where I come unstuck.

How do I pass back the results (Global port?) AND more importantly: How do I plug the CCR into the WCF Asynchronous Service Call without blocking a Thread?

public IEnumerator<ITask> GetAccount(int id)
    {
        SqlDataReader reader = null; 
        SqlConnection connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=BizData;Integrated Security=True;Async=True;"); 
        string query = "SELECT * FROM Account WHERE AccountID = @AccountID"; 
        SqlCommand command = new SqlCommand(query, connection);
        SqlParameter accountID = new SqlParameter("AccountID", id);
        command.Parameters.Add(accountID);

        connection.Open(); 
        yield return Arbiter.Choice(SQLAdapter.GetReader(command), 
            delegate(SqlDataReader r) { reader = r; }, 
            delegate(Exception e) { Console.Write("Failed to get SQL data"); }); 

        if (reader == null) yield break;       

        while (reader.Read())       
        {
            Account account = new Account { ID = Convert.ToInt32(reader["AccountID"]), 
                Name = reader["Account"].ToString(), 
                ParkingNo = Convert.ToInt32(reader["ParkingNo"]), 
                Password = reader["Password"].ToString() };
            //Post account?
        }
        connection.Close(); 
    }

解决方案

OK i finally got somewhere with all of this!

First up: You need a custom AsyncResult Class

class AsyncResult : IAsyncResult , IDisposable
    {
        object _state;
        ManualResetEvent _waitHandle = new ManualResetEvent(false);
        bool _isCompleted;

        #region IAsyncResult Members
        public object AsyncState
        {
            get { return _state; }
        }

        public System.Threading.WaitHandle AsyncWaitHandle
        {
            get { return _waitHandle; }
        }

        public bool CompletedSynchronously
        {
            get { return false; }
        }

        public bool IsCompleted
        {
            get { return _isCompleted; }
        }
        #endregion

        Exception _exception;
        internal Exception Exception
        {
            get { return _exception; }
        }

        Accounts.Account _result;
        internal Accounts.Account Result
        {
            get { return _result; }
        }

        internal AsyncResult(PortSet<Accounts.Account, Exception> port, DispatcherQueue queue, AsyncCallback callback, object state)
        {
            _state = state;

            Arbiter.Activate(queue,
                Arbiter.Choice(port,
                    r =>
                    {
                        _result = r;
                        Complete(callback);
                    },
                    e =>
                    {
                        _exception = e;
                        Complete(callback);
                    }
                )
            );
        }

        private void Complete(AsyncCallback callback)
        {
            _isCompleted = true;
            _waitHandle.Set();

            if (callback != null)
            {
                ThreadPool.QueueUserWorkItem(s => callback(this));
            }
        }

        private bool disposedValue = false;

        public void Dispose()
        {
            if (!this.disposedValue)
            {
                _waitHandle.Close();
                _waitHandle = null;
                _state = null;
            }
            this.disposedValue = true;
        }
    }

Ok, then we need to tie this in with the Async WCF Method calls:

public class Service : IService
    {
        private Dispatcher dispatcher;
        private DispatcherQueue dq;

        public Service() 
        {
             dispatcher = new Dispatcher();
             dq = new DispatcherQueue("CCR DispatcherQueue", dispatcher);
        }

        public IAsyncResult BeginGetAccount(int id, AsyncCallback callback, object state)
        {
            PortSet<Accounts.Account, Exception> port = new PortSet<Accounts.Account, Exception>();
            Accounts.Manager manager = new Accounts.Manager();
            manager.GetAccountData(dq, port, id);

            AsyncResult result = new AsyncResult(port, dq, callback, state);
            return result;
        }

        public string EndGetAccount(IAsyncResult result)
        {
            {
                var AccountName = string.Empty;
                if ((result != null))
                {
                    using (Common.AsyncResult asyncResult = result as Common.AsyncResult)
                    {

                        if (asyncResult == null)
                        {
                            throw new NullReferenceException("IAsynchResult Parameter is Null");
                        }

                        asyncResult.AsyncWaitHandle.WaitOne();
                        if (asyncResult.Result != null) 
                        { 
                            AccountName = asyncResult.Result.Name; 
                        }
                    }
                }
                return AccountName;
            }
        }
    }

Then you just need the IEnumerator method to post the answer to the port

这篇关于使用异步WCF服务的CCR的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆