您的位置:首页 > 产品设计 > UI/UE

从UI体验下异步调用的四种方法

2008-04-20 15:25 375 查看
我下面的DEMO是从MSDN下摘抄过来的,可是MSDN是从控制台打印出来,

如果要比较直观地理解线程间的操作,从直观体验上觉得还是直接从UI方面感觉比较好

而下面主要是介绍那四处方法的使用,为什么用,怎么用,

因为除了第一种异步回调之外,其他的界面都卡在那里一动不动,但并不是说其他三种不好,只是他们还有别的地方要用而已

而里面红色的注释,我想已经能表达我想说的,而代码我还不知怎么像有的朋友那样贴上去好看点,可能比较难看,将就点喽

//委托,其就是函数签名,从这里可以看出,参数与返回值是与函数一模一样的,

//而委托主要也是用于回调同步异步,观察者模式,改天再好好回味一下观察者模式

public delegate string AsyncMethodCaller(int callDuration, out int threadId);

//这里写上返回值只是为了好玩,经常写没返回值的委托,写写看,嘿嘿

public delegate string InvokeMethodCaller(string s);

class AsyncDemo

{

// The method to be executed asynchronously.

public string TestMethod(int callDuration, out int threadId)

{

Console.WriteLine("Test method begins.");

for (int i = 0; i < callDuration / 1000; i++)

{

Console.WriteLine("次线程:" + callDuration);

Thread.Sleep(1000);

}

threadId = Thread.CurrentThread.ManagedThreadId;

Console.WriteLine(threadId.ToString());

return String.Format("My call time was {0}.", callDuration.ToString());

}

}

private static int threadId;

public Form1()

{

InitializeComponent();

}

private void button1_Click(object sender, EventArgs e)

{

//变量

string rethrnValue = string.Empty;

AsyncDemo ad = new AsyncDemo();

//把AD对象的TestMethod方法注册给了AsyncMethodCaller委托,实例名CallbackEvent,

//再由这个CallbackEvent去异步调用,BeginInvoke ,EndInvoke,Invoke等三个同异步方法

//而为什么有this.invoke这个嘛!就不知跟这里所说的一样不,希望有朋友给我指出下,谢谢

AsyncMethodCaller CallbackEvent = new AsyncMethodCaller(ad.TestMethod);

//方法1,指定一个回调函数,可惜在回调函数里还是必须得用INVOKE,证明,

//得到的数据还是在别的线程而已,而CONSOLE,MESSAGEBOX能用只能说是静态的

//如果启动异步调用的线程不需要是处理结果的线程,则可以在调用完成时执行回调方法。回调方法在 ThreadPool 线程上执行。

//若要使用回调方法,必须将引用回调方法的 AsyncCallback 委托传递给 BeginInvoke。

//也可以传递包含回调方法将要使用的信息的对象。例如,可以传递启动调用时曾使用的委托,以便回调方法能够调用 EndInvoke。

//主要理解回调方法将要使用的信息的对象,IAsyncResult,这个,也可以理解下

//回调的方法 new AsyncCallback(Callback)

//使用的委托 CallbackEvent

//前两个是委托的参数

CallbackEvent.BeginInvoke(3000, out threadId, new AsyncCallback(Callback), CallbackEvent);

//方法2 一直轮循,一直都是UI线程在调,判断是否完成

//MSDN:您可以使用由 BeginInvoke 返回的 IAsyncResult 的 IsCompleted 属性来发现异步调用何时完成。

//从用户界面的服务线程中进行异步调用时可以执行此操作。

//轮询完成允许调用线程在异步调用在 ThreadPool 线程上执行时继续执行。

//尽管的确是界面也可以操作,但是,实际上来拖动界面是很难的,证明这时间是很短的,

//对于显示一个固定的界面不能动的进度条还可以考虑下,其他的

//愚见就算了吧,就用第一种吧,其实这下三种道理都是一样的,开启一线程在做,主线程等待,等其完成,取其返回值,

//但我们知道,在NET1.1线程间想传值是很麻烦,而二点零回调等等,则帮我们做了这么些事情吧

//IAsyncResult ar1 = CallbackEvent.BeginInvoke(3000, out threadId, null, null);

//while (!ar1.IsCompleted)

//{

// //Thread.Sleep(20);

// //richTextBox1.Text += 8 + ""n";

//}//循环直到异步完成

// rethrnValue = CallbackEvent.EndInvoke(out threadId, ar1);

//richTextBox1.Text += rethrnValue + " " + threadId;

//方法3 使用WAITONE,其实道理与轮循一样,或许只是少了个WHILE循环

//MSDN :如果您使用 WaitHandle,则在异步调用完成之前或之后,在通过调用 EndInvoke 检索结果之前,还可以执行其他处理。

//其实跟上下两种方法是一样的,感觉好拙呀!只是写法不同而已

//IAsyncResult result = CallbackEvent.BeginInvoke(3000, out threadId, null, null);

//// while (!result.IsCompleted)

////{

//// Application.DoEvents();

////}

//result.AsyncWaitHandle.WaitOne();

//rethrnValue = CallbackEvent.EndInvoke(out threadId, result);

//richTextBox1.Text += rethrnValue + " " + threadId.ToString();

//方法四 一BeginInvoke,另一线程就启动,而在与EndInvoke之间,主线程是可以干这里面代码的事情的,

//MSDN:EndInvoke 可能会阻止调用线程,因为它直到异步调用完成之后才返回。

//这种技术非常适合文件或网络操作,但是由于 EndInvoke 会阻止它,所以不要从服务于用户界面的线程中调用它。

//IAsyncResult result = CallbackEvent.BeginInvoke(3000, out threadId, null, null);

////while (!result.IsCompleted)

////{

//// Application.DoEvents();

////}

// rethrnValue = CallbackEvent.EndInvoke(out threadId, result);

//richTextBox1.Text += rethrnValue + " " + threadId.ToString();

}

private void Callback(IAsyncResult ar)

{

AsyncMethodCaller caller = (AsyncMethodCaller)ar.AsyncState;

string s = caller.EndInvoke(out threadId, ar);

//如果这样写,其实就是另开一个同步调用了,而把上面那个异步调用再做一遍,一时很傻的想法

//放在这里是想说明下同步而已

//string s = caller.Invoke(3000, out threadId);

//而如果用下面这个,则会发生线程间调用的问题,提示不是从创建线程赋值的,一般这种问题都是没有与UI线程同步

//richTextBox1.Text += threadId;

//与UI线程同步的写法

this.Invoke(new InvokeMethodCaller(setText), s);

}

private string setText(string s)

{

//到这里了,已经是跟UI是同一线程的了

richTextBox1.Text += s;

return s;

}

而里面////的地方是我特意测试用的,偶尔可能还能让你体会一下,代码很短,或许你COPY一下就可以在自已机子上运行,但跟着抄一遍,最好是理解后自已写一份出来,或许收益更大吧

改天再把读取网络大的文件流,SOCKET等等结合下写出来,希望朋友指出错误,谢谢

加油EVERYONE

[转自]http://www.cnblogs.com/yellowyu/archive/2008/03/31/1131077.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: