基元用户模式构造--互锁构造 Interlocked 实现的异步web请求实例

时间:2023-03-09 09:12:24
基元用户模式构造--互锁构造 Interlocked 实现的异步web请求实例
 using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace Test
{
enum CoordinationStatus
{
AllDone,
Cancel,
Timeout
}
class AsyncCoordinator
{
private int statusReported = ;
private int op_count = ; private Action<CoordinationStatus> callback;
private Timer timer; public void AboutToBegin(int num = )
{
Interlocked.Add(ref op_count, num);
} public void JustToEnd()
{
if (Interlocked.Decrement(ref op_count) == )
{
ReportStatus(CoordinationStatus.AllDone);
}
} public void AllBegun(Action<CoordinationStatus> callback, int timeout = Timeout.Infinite)
{
this.callback = callback;
if (timeout != Timeout.Infinite)
{
timer = new Timer(Expired, null, timeout, Timeout.Infinite);
}
JustToEnd();
} private void Expired(object obj)
{
ReportStatus(CoordinationStatus.Cancel);
}
public void Cancel()
{
ReportStatus(CoordinationStatus.Cancel);
}
private void ReportStatus(CoordinationStatus status)
{
if (Interlocked.Exchange(ref statusReported, ) == )
{
callback(status);
}
} } class MultiWebRequests
{
private AsyncCoordinator coordinator = new AsyncCoordinator(); private Dictionary<string, object> servers = new Dictionary<string, object>(){
{"http://www.baidu.com",null},
{"http://www.sina.com",null},
{"http://www.qq.com",null},
}; public MultiWebRequests()
{ var http = new HttpClient();
foreach (var url in servers.Keys)
{
//发送了一个请求
coordinator.AboutToBegin();
http.GetByteArrayAsync(url).ContinueWith(task => GetResult(url, task));
}
//所有请求发送完毕
coordinator.AllBegun(AllDone, Timeout.Infinite);
} private void GetResult(string server, Task<byte[]> task)
{
object res;
if (task.Exception != null)
{
res = task.Exception.InnerExceptions;
}
else
{
res = task.Result.Length;
}
servers[server] = res;
//完成了一个请求
coordinator.JustToEnd();
} public void Cancel()
{
coordinator.Cancel();
} private void AllDone(CoordinationStatus status)
{
switch (status)
{
case CoordinationStatus.AllDone:
Console.WriteLine("allDone: "); foreach (var item in servers)
{
Console.Write(item.Key);
object val = item.Value;
if (val is Exception)
{
Console.WriteLine("Exception: {0}",val.GetType().Name);
}
else
{
Console.WriteLine("returned {0:N0} bytes",val);
}
}
break;
case CoordinationStatus.Cancel:
break;
case CoordinationStatus.Timeout:
break;
default:
break;
}
}
}
}