namespace ConsoleApp21
{
//完成,超时,取消
internal enum CoordinationStatus { AllDone,Timeout,Cancel }; //协调状态
internal sealed class AsyncCoordinator
{
int m_opCount = 1; //计数
int m_statusReported = 0; //状态报告
Action<CoordinationStatus> m_callback; //回调
Timer m_timer; //时间
public void AboutToBegin(int opsToAdd=1) //开始
{ //每次增加opsToAdd
Interlocked.Add(ref m_opCount, opsToAdd);
}
public void JustEnded()//结束
{
if (Interlocked.Decrement(ref m_opCount) == 0) //返回递减后的值,查看是否为0
ReportStatus(CoordinationStatus.AllDone);
}
public void AllBegun(Action<CoordinationStatus> callback
, int timeout = Timeout.Infinite)
{
m_callback = callback;
if (timeout != Timeout.Infinite) //如果传递的参数不等于超时值,调用回调一次
m_timer = new Timer(TimeExpired, null, timeout, Timeout.Infinite);
JustEnded(); //递减计数
}
void TimeExpired(object o) //过期(超时)
{
ReportStatus(CoordinationStatus.Timeout);
}
public void Cancel()
{
ReportStatus(CoordinationStatus.Cancel);
}
void ReportStatus(CoordinationStatus status)
{
if (Interlocked.Exchange(ref m_statusReported, 1) == 0) //只调用1次
m_callback(status);
}
}
internal sealed class MultiWebRequests
{
AsyncCoordinator m_ac = new AsyncCoordinator();
Dictionary<string, object> m_servers = new Dictionary<string, object>
{
{ "http://Wintellect.com/",null },
{ "http://Microsoft.com/",null},
{ "http://1.1.1.1/",null}
};
public MultiWebRequests(int timeout = Timeout.Infinite)//Web请求
{
HttpClient httpClient = new HttpClient();
foreach (string server in m_servers.Keys)
{
m_ac.AboutToBegin(1); //计数+1,每次
httpClient.GetByteArrayAsync(server).ContinueWith
(task => ComputeResult(server, task));
}
m_ac.AllBegun(AllDone, timeout); //注册回调方法,传递是否 触发 参数
}
void ComputeResult(string server, Task<byte[]> task) //延续任务
{
object result = null;
if (task.Exception != null) //引发了异常
result = task.Exception.InnerException; //result装载异常
else //未引发异常
result = task.Result.Length; //装载数组的长度
m_servers[server] = result; //查询字典
m_ac.JustEnded(); //递减计数,递减为0触发报告
}
public void Cancel() //取消
{
m_ac.Cancel();
}
void AllDone(CoordinationStatus status)
{
switch (status)
{
case CoordinationStatus.Cancel:
Console.WriteLine("取消");break;
case CoordinationStatus.Timeout:
Console.WriteLine("超时");break;
case CoordinationStatus.AllDone:
{
Console.WriteLine("完成");
foreach (var server in m_servers)
{
Console.Write("{0}", server.Key);
object result = server;
if (result is Exception) //如果装载了异常
Console.WriteLine(" 异常,{0}", result.GetType().Name);
else
Console.WriteLine(" 长度,{0}", result);
}
break;
}
}
}
}
class Myclass
{
static void Main()
{
MultiWebRequests t = new MultiWebRequests(1);
t.Cancel();
Console.ReadLine();
}
}
}
构造必然在调用t.cancel()前完成,
构造内部的m_ac.AllBegun(AllDone, timeout);
由于我构造的时候传递了一个超时参数 1 ,
m_timer = new Timer(TimeExpired, null, timeout, Timeout.Infinite); 必然会被调用,最后输出 超时
但是执行的时候输出值 有两种情况, 超时 或者 取消,
但是按流程取消的函数内部调用必然不会被调用,但是结果就是有可能取消先
为什么会这样???
Timer是由线程池线程提供服务,你的m_timer = new Timer(TimeExpired, null, 1, Timeout.Infinite); 表示调用TimeExpired之前延迟1ms。所以是有可能在这1ms内cancel方法被执行的