【发布时间】:2018-12-27 23:19:25
【问题描述】:
如果我在这个逻辑中有一些错误,请纠正我(不是一些优雅的事情,比如摆脱构造函数初始化并使用 Init 方法代替 Poll)。到目前为止,我还没有使用计时器回调的经验。我希望,代码是不言自明的。让我有点困惑的是一些异步的东西(比如创建连接客户端)和更多的代码——不过,我只是重用了 IClient 类,它不是我的):
public async Task<WaitForLoanActivationDto> WaitForLoanActivation(string userName, string accountGuid, int timeout)
{
const int dueTime = 0;
const int pollPeriod = 500;
Poll<WaitForLoanActivationDto> state = new Poll<WaitForLoanActivationDto>
{
Client = await _rpcConnectionPool.GetClientAsync(userName),
AutoResetEvent = new AutoResetEvent(false),
StartTime = DateTime.Now,
Timeout = timeout,
Parameters = new Variant[] { accountGuid },
Result = new WaitForLoanActivationDto { Active = false }
};
Timer timer = new Timer(new TimerCallback(WaitForLoanActivationCallback), state, dueTime, pollPeriod);
state.AutoResetEvent.WaitOne();
timer.Dispose(state.AutoResetEvent);
if (state.ThreadException != null)
{
throw state.ThreadException;
}
return state.Result;
}
private void WaitForLoanActivationCallback(object state)
{
Poll<WaitForLoanActivationDto> pollState = (Poll<WaitForLoanActivationDto>)state;
if (pollState.StartTime.AddMilliseconds(pollState.Timeout) >= DateTime.Now)
{
try
{
using (RPCReply reply = ResultHelper.Check(pollState.Client.ExecuteRemoteCommand(WaitForLoanActivationRpcName, pollState.Parameters)))
{
pollState.Result.Active = reply[2].IDList["Active"].AsBoolean().Value;
VariantList statusList = reply[2].IDList["statuses"].List;
if (statusList.Count > 0)
{
var statuses = CustomerInformationConverter.GetStatusesList(statusList);
pollState.Result.Statuses = statuses.ToArray();
}
if (pollState.Result.Active)
{
pollState.AutoResetEvent.Set();
}
}
}
catch (Exception ex)
{
pollState.Result = null;
pollState.ThreadException = ex;
pollState.AutoResetEvent.Set();
}
}
else
{
pollState.AutoResetEvent.Set();
}
}
【问题讨论】:
-
我会放弃计时器,以获得完整的异步解决方案,使用 Task.Delay 循环进行轮询。这也将消除 AutoResetEvent 的必要性并使代码更清晰。此外,由于 AutoResetEvent 并且您在等待它,您也阻塞了一个线程,我猜它可能会停止您的 UI,而 Task.Delay 不会出现这种情况。
-
是的,我必须同意这段代码相当做作,你正在创建一个状态机,
GetClientAsync然后启动一个计时器并阻塞调用线程,同时计时器创建新线程来做某事或其他事情,完成后,它让原始线程继续。似乎它是从旧式代码重构而来的
标签: c# timer exception-handling async-await autoresetevent