2

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

这是测试 WCF 服务:

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

它需要一个 ID 号并返回匹配的帐户名称(如果有)

我编写了一个 CCR 函数,它应该找到匹配的帐户(显然需要大量工作 - 这只是概念证明)这是我遇到的问题。

如何传回结果(全局端口?)更重要的是:如何在不阻塞线程的情况下将 CCR 插入 WCF 异步服务调用?

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

2 回答 2

1

好的,我终于找到了所有这些的地方!

首先:您需要一个自定义 AsyncResult 类

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

好的,那么我们需要将其与 Async WCF 方法调用联系起来:

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

然后你只需要 IEnumerator 方法将答案发布到端口

于 2009-02-03T22:43:13.540 回答
0

有关端到端示例,请参阅此博客:

使用 CCR 的 WCF 服务的异常处理、排队和 UI 同步

于 2009-04-06T18:35:10.370 回答