使用异步WCF服务的CCR [英] Using the CCR with ASynchronous WCF Service
问题描述
我正在学习如何结合一个异步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屋!