C# 异步委托总结
C#的异步委托,总感觉十分的古老,虽然现在又新出了异步方法(async/await),但是在一些老的项目中并不支持新的语法,所以还得会用,参考一些网上大神的笔记,在这里将C#古老的异步委托,总结一下,以备不时之需。
1. BeginInvoke与EndInvoke
//建立委托
MyDelegate myDelegate = new MyDelegate(Hello);
//异步调用委托,获取计算结果
IAsyncResult result = myDelegate.BeginInvoke("Leslie", null, null);
//完成主线程其他工作
Console.WriteLine(".............");
//等待异步方法完成,调用EndInvoke(IAsyncResult)获取运行结果
string data = myDelegate.EndInvoke(result);
Console.WriteLine(data);
delegate string MyDelegate(string name);
static string Hello(string name)
{
Thread.Sleep(2000);
return "Hello " + name;
}
2. 轮询方式
//建立委托
MyDelegate myDelegate = new MyDelegate(Hello);
//异步调用委托,获取计算结果
IAsyncResult result = myDelegate1.BeginInvoke("Leslie", null, null);
//在异步线程未完成前执行其他工作
while (!result.IsCompleted)
{
Thread.Sleep(200);
Console.WriteLine("Main thead do work!");
}
while (!result.AsyncWaitHandle.WaitOne(200))
{
Console.WriteLine("Main thead do work!");
}
string data = myDelegate.EndInvoke(result);
Console.WriteLine(data);
3. 回调函数
//建立委托
MyDelegate myDelegate = new MyDelegate(Hello);
//异步调用委托,获取计算结果
myDelegate.BeginInvoke("Leslie", new AsyncCallback(Completed), null);
//建立Person对象
Person person = new Person();
person.Name = "Elva";
person.Age = 27;
//异步调用委托,输入参数对象person, 获取计算结果
myDelegate.BeginInvoke("Leslie", new AsyncCallback(Completed3), person);
//在启动异步线程后,主线程可以继续工作而不需要等待
for (int n = 0; n < 6; n++)
{
Console.WriteLine(" Main thread do work!");
}
static void Completed(IAsyncResult result)
{
//获取委托对象,调用EndInvoke方法获取运行结果
AsyncResult _result = (AsyncResult)result;
MyDelegate myDelegate = (MyDelegate)_result.AsyncDelegate;
string data = myDelegate.EndInvoke(_result);
Console.WriteLine(data);
}
static void Completed3(IAsyncResult result)
{
//获取委托对象,调用EndInvoke方法获取运行结果
AsyncResult _result = (AsyncResult)result;
MyDelegate myDelegate = (MyDelegate)_result.AsyncDelegate;
string data = myDelegate.EndInvoke(_result);
//获取Person对象
Person person = (Person)result.AsyncState;
string message = person.Name + "'s age is " + person.Age.ToString();
Console.WriteLine(data + "\n" + message);
}
4. 异步读写文件
//把线程池的最大值设置为1000
ThreadPool.SetMaxThreads(1000, 1000);
ThreadPoolMessage("Start");
#region 异步写文件
//新立文件temp.txt
FileStream stream0 = new FileStream("temp.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 1024, true);
byte[] bytes = new byte[16384];
string message = "An operating-system ThreadId...";
bytes = Encoding.Unicode.GetBytes(message);
//启动异步写入
stream0.BeginWrite(bytes, 0, (int)bytes.Length, new AsyncCallback(CallbackWrite), stream0);
stream0.Flush();
#endregion
#region 异步读文件
byte[] byteData = new byte[80961024];
FileStream stream1 = new FileStream("temp.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 1024, true);
/*把FileStream对象,byte[]对象,
长度等有关数据绑定到FileData对象中,
以附带属性方式送到回调函数
*/
FileData fileData = new FileData();
fileData.Stream = stream1;
fileData.Length = (int)stream1.Length;
fileData.ByteData = byteData;
//启动异步读取
stream1.BeginRead(byteData, 0, fileData.Length, new AsyncCallback(CallbackRead), fileData);
#endregion
Console.ReadKey();
}
/// <summary>
/// 写文件的回调函数
/// </summary>
/// <param name="result"></param>
static void CallbackWrite(IAsyncResult result)
{
//显示线程池现状
Thread.Sleep(200);
ThreadPoolMessage("CallbackWrite");
//结束异步写入
FileStream stream = (FileStream)result.AsyncState;
stream.EndWrite(result);
stream.Close();
}
//显示线程池现状
static void ThreadPoolMessage(string data)
{
int a, b;
ThreadPool.GetAvailableThreads(out a, out b);
string message = string.Format("{0}\n CurrentThreadId is {1}\n " + "WorkerThreads is:{2} CompletionPortThreads is :{ 3}",
data, Thread.CurrentThread.ManagedThreadId, a.ToString(), b.ToString());
Console.WriteLine(message);
}
public class FileData
{
public FileStream Stream;
public int Length;
public byte[] ByteData;
}
/// <summary>
/// 读文件的回调函数
/// </summary>
/// <param name="result"></param>
static void CallbackRead(IAsyncResult result)
{
ThreadPoolMessage("CallbackRead");
//把AsyncResult.AsyncState转换为FileData对象,以FileStream.EndRead完成异步读取
FileData fileData = (FileData)result.AsyncState;
int length = fileData.Stream.EndRead(result);
fileData.Stream.Close();
//如果读取到的长度与输入长度不一致,则抛出异常
if (length != fileData.Length)
throw new Exception("Stream is not complete!");
string data = Encoding.ASCII.GetString(fileData.ByteData, 0, fileData.Length);
Console.WriteLine(data.Substring(2, 22));
}
5. 跨线程访问
//跨线程访问
Thread thread1 = new Thread(SetValues);
thread1.IsBackground = true;
thread1.Start();
//新线程给文本框赋值
private void SetValues()
{
Action<int> setVal = (i) => { this.myTxtBox.Text = i.ToString(); };
for (int i = 0; i < 10000; i++)
{
this.myTxtBox.Invoke(setVal, i);
}
}