问题描述
最近在学习线程这部分,有一段代码不是很明白,请各位大牛不吝赐教,谢谢。voidbutton_Click(objectsender,RoutedEventArgse){CalculateHandlercalculateHandler=Calculate;AsyncCallbackasyncCallback=CalculateCallBack;calculateHandler.BeginInvoke(100,200,asyncCallback,calculateHandler);}publicdelegateintCalculateHandler(inta,intb);privateintCalculate(inta,intb){Thread.Sleep(5000);returna+b;}privatevoidCalculateCallBack(IAsyncResultasyncResult){if(asyncResult==null)return;if(textblock.CheckAccess()){textblock.Text=(asyncResult.AsyncStateasCalculateHandler).EndInvoke(asyncResult).ToString();}else{textblock.Dispatcher.Invoke(delegate(){textblock.Text=(asyncResult.AsyncStateasCalculateHandler).EndInvoke(asyncResult).ToString();});}}
1.点击事件中第三句,calculateHandler.BeginInvoke()这个方法为什么找不到声明的地方?按F12会调到委托类型CalculateHandler声明的地方。2.点击事件中第三句,calculateHandler.BeginInvoke()的最后一个参数传入的是委托实例自身,这样做有什么意义?3.调用回调函数CalculateCallBack的时候,为什么参数asyncResult不为null?传入这个参数的地方在哪?
解决方案
解决方案二:
哦还忘了一个问题,回调函数CalculateCallBack中的第四句:EndInvoke()这个方法用法是什么?BeginInvoke(100,200,asyncCallback,calculateHandler)是不是把最后一个参数赋给asyncCallback指向的方法的参数(IAsyncResult)的AsyncState属性?
解决方案三:
1.点击事件中第三句,calculateHandler.BeginInvoke()这个方法为什么找不到声明的地方?按F12会调到委托类型CalculateHandler声明的地方。BeginInvoke和EndInvoke是编译器根据参数列表自动生成的,所以你找不到2.点击事件中第三句,calculateHandler.BeginInvoke()的最后一个参数传入的是委托实例自身,这样做有什么意义?传自身是多余的,最后一个参数是提供给回调时记录状态用的,回调的时候可以从AsyncResult.AsyncState这个属性里拿到这个时候AsyncResult.AsyncDelegate属性就是那个委托实例3.调用回调函数CalculateCallBack的时候,为什么参数asyncResult不为null?传入这个参数的地方在哪?看2
解决方案四:
引用1楼h2041075的回复:
哦还忘了一个问题,回调函数CalculateCallBack中的第四句:EndInvoke()这个方法用法是什么?BeginInvoke(100,200,asyncCallback,calculateHandler)是不是把最后一个参数赋给asyncCallback指向的方法的参数(IAsyncResult)的AsyncState属性?
voidasyncCallback(IAsyncResultar){((arasAsyncResult).AsyncDelegateas%%%%%%).EndInvoke(*******,ar);}%%%%%%就是你委托的类型*******是你如果定义了ref/out参数,这里可以拿到,否则就只有EndInvoke(ar);
解决方案五:
引用2楼shingoscar的回复:
1.点击事件中第三句,calculateHandler.BeginInvoke()这个方法为什么找不到声明的地方?按F12会调到委托类型CalculateHandler声明的地方。BeginInvoke和EndInvoke是编译器根据参数列表自动生成的,所以你找不到2.点击事件中第三句,calculateHandler.BeginInvoke()的最后一个参数传入的是委托实例自身,这样做有什么意义?传自身是多余的,最后一个参数是提供给回调时记录状态用的,回调的时候可以从AsyncResult.AsyncState这个属性里拿到这个时候AsyncResult.AsyncDelegate属性就是那个委托实例3.调用回调函数CalculateCallBack的时候,为什么参数asyncResult不为null?传入这个参数的地方在哪?看2
谢谢解答。第一个问题明白了。第二个问题貌似不太对:回调函数的参数IAsyncResult.AsyncState应该就是BeginInvoke()的最后一个参数。如果BeginInvoke的时候最后一个参数传null,那么在回调函数中设置断点的话IAsyncResult.AsyncDelegate确实就是委托实例本身,但是这个属性点不出来就说不能用。所以只能通过IAsyncResult.AsyncState来活动委托实例本身,而想获得IAsyncResult.AsyncState则需要在BeginInvoke()方法的最后一个参数传入委托实例本身。
解决方案六:
引用2楼shingoscar的回复:
1.点击事件中第三句,calculateHandler.BeginInvoke()这个方法为什么找不到声明的地方?按F12会调到委托类型CalculateHandler声明的地方。BeginInvoke和EndInvoke是编译器根据参数列表自动生成的,所以你找不到2.点击事件中第三句,calculateHandler.BeginInvoke()的最后一个参数传入的是委托实例自身,这样做有什么意义?传自身是多余的,最后一个参数是提供给回调时记录状态用的,回调的时候可以从AsyncResult.AsyncState这个属性里拿到这个时候AsyncResult.AsyncDelegate属性就是那个委托实例3.调用回调函数CalculateCallBack的时候,为什么参数asyncResult不为null?传入这个参数的地方在哪?看2
这是截图,不管BeginInvoke()的最后一个参数传的是什么,在断点中IAsyncResult.AsyncDelegate确实都是委托实例本身。但是如果不显示传入这个参数,那么在回调函数中根本点不出来这个属性?所以想在回调函数中获得委托实例,还是需要在BeginInvoke()中显示传入委托实例本身作为参数。
解决方案七:
引用2楼shingoscar的回复:
1.点击事件中第三句,calculateHandler.BeginInvoke()这个方法为什么找不到声明的地方?按F12会调到委托类型CalculateHandler声明的地方。BeginInvoke和EndInvoke是编译器根据参数列表自动生成的,所以你找不到2.点击事件中第三句,calculateHandler.BeginInvoke()的最后一个参数传入的是委托实例自身,这样做有什么意义?传自身是多余的,最后一个参数是提供给回调时记录状态用的,回调的时候可以从AsyncResult.AsyncState这个属性里拿到这个时候AsyncResult.AsyncDelegate属性就是那个委托实例3.调用回调函数CalculateCallBack的时候,为什么参数asyncResult不为null?传入这个参数的地方在哪?看2
补上截图。。又忘了。。
解决方案八:
你看清楚啊,我写的是AsyncResult没有开头的I
解决方案九:
引用1楼h2041075的回复:
哦还忘了一个问题,回调函数CalculateCallBack中的第四句:EndInvoke()这个方法用法是什么?BeginInvoke(100,200,asyncCallback,calculateHandler)是不是把最后一个参数赋给asyncCallback指向的方法的参数(IAsyncResult)的AsyncState属性?
明白了....原来IAsyncResult还要先转成AsyncResult...。
解决方案十:
谢谢谢谢...其实我补完截图就发现了,不过csdn不能连续三次发帖,没法及时回复你,蛋疼...
解决方案十一:
引用7楼shingoscar的回复:
你看清楚啊,我写的是AsyncResult没有开头的I
能不能再给说下Control.BeginInvoke和Delegate.BeginInvoke的联系?Control.BeginInvoke可以理解成安全地在控件所属线程中更改控件的属性吧?那么Delegate.BeginInvoke要怎么理解?好像Delegate.BeginInvoke的资料比较少,大都是关于控件的。
解决方案十二:
能不能再给说下Control.BeginInvoke和Delegate.BeginInvoke的联系?它们的名称是一样的Control.BeginInvoke可以理解成安全地在控件所属线程中更改控件的属性吧?对的那么Delegate.BeginInvoke要怎么理解?好像Delegate.BeginInvoke的资料比较少,大都是关于控件的。就是在一个单独的线程中运行这个方法
解决方案十三:
引用11楼shingoscar的回复:
能不能再给说下Control.BeginInvoke和Delegate.BeginInvoke的联系?它们的名称是一样的Control.BeginInvoke可以理解成安全地在控件所属线程中更改控件的属性吧?对的那么Delegate.BeginInvoke要怎么理解?好像Delegate.BeginInvoke的资料比较少,大都是关于控件的。就是在一个单独的线程中运行这个方法
Delegate.BeginInvoke:很好理解,异步执行此委托(方法)。Control.BeginInvoke和Control.Invoke:都会在UI线程执行,只是后者会阻塞调用者,前者则不会。
解决方案十四:
引用11楼shingoscar的回复:
能不能再给说下Control.BeginInvoke和Delegate.BeginInvoke的联系?它们的名称是一样的Control.BeginInvoke可以理解成安全地在控件所属线程中更改控件的属性吧?对的那么Delegate.BeginInvoke要怎么理解?好像Delegate.BeginInvoke的资料比较少,大都是关于控件的。就是在一个单独的线程中运行这个方法
voidbutton_Click(objectsender,RoutedEventArgse){CalculateHandlercalculateHandler=Calculate;calculateHandler.BeginInvoke(100,200,CalculateCallBack,calculateHandler);}publicdelegateintCalculateHandler(inta,intb);privateintCalculate(inta,intb){Thread.Sleep(5000);returna+b;}privatevoidCalculateCallBack(IAsyncResultasyncResult){if(asyncResult==null)return;if(textblock.CheckAccess()){textblock.Text=(asyncResult.AsyncStateasCalculateHandler).EndInvoke(asyncResult).ToString();}else{textblock.Dispatcher.Invoke(delegate(){textblock.Text=(asyncResult.AsyncStateasCalculateHandler).EndInvoke(asyncResult).ToString();});}}
点击事件中这一句:calculateHandler.BeginInvoke(100,200,CalculateCallBack,calculateHandler);它没有给回调方法CalculateCallBack方法传入实参啊,为什么执行CalculateCallBack的时候形参IAsyncResultasyncResult会有值呢?这个值是不是在委托实例calculateHandler所指向的方法执行的时候产生的?
解决方案十五:
引用11楼shingoscar的回复:
能不能再给说下Control.BeginInvoke和Delegate.BeginInvoke的联系?它们的名称是一样的Control.BeginInvoke可以理解成安全地在控件所属线程中更改控件的属性吧?对的那么Delegate.BeginInvoke要怎么理解?好像Delegate.BeginInvoke的资料比较少,大都是关于控件的。就是在一个单独的线程中运行这个方法
voidbutton_Click(objectsender,RoutedEventArgse){CalculateHandlercalculateHandler=Calculate;IAsyncResultasyncResult=calculateHandler.BeginInvoke(100,200,null,null);asyncResult.AsyncWaitHandle.WaitOne();textblock.Text=calculateHandler.EndInvoke(asyncResult).ToString();}
点击事件中,asyncResult.AsyncWaitHandle.WaitOne();这一句有什么意义呢?有没有这句都要等待5秒钟,如果有这句,那么断点在asyncResult.AsyncWaitHandle.WaitOne()之后等待;如果没有这句,那么断点在textblock.Text=calculateHandler.EndInvoke(asyncResult).ToString()之后等待。
解决方案:
别去学那个了太复杂了asyncvoidbutton_Click(objectsender,RoutedEventArgse){awaitTask.factory.startnew(()=>{耗时操作});}
解决方案:
privateasyncvoidbutton1_Click(objectsender,EventArgse){awaitTask.Factory.StartNew(()=>{stringwork="weiwancheng";Thread.Sleep(5000);work="wancheng";this.Invoke((MethodInvoker)(()=>{this.button1.Text=$"renwu{work}";}));});}
解决方案:
引用15楼fancky2010的回复:
别去学那个了太复杂了asyncvoidbutton_Click(objectsender,RoutedEventArgse){awaitTask.factory.startnew(()=>{耗时操作});}
这是什么用法。。。大概给说明一下呗,这个async和await怎么用啊?Task又是干什么用的。。你这个方法比用委托方便的多啊。
解决方案:
引用16楼fancky2010的回复:
privateasyncvoidbutton1_Click(objectsender,EventArgse){awaitTask.Factory.StartNew(()=>{stringwork="weiwancheng";Thread.Sleep(5000);work="wancheng";this.Invoke((MethodInvoker)(()=>{this.button1.Text=$"renwu{work}";}));});}
刚刚找了一下这方面的资料,基本上都是概述,没有Task、async、await组合起来的比较详细的文档,能不能帮忙找一下?
解决方案:
1.点击事件中第三句,calculateHandler.BeginInvoke()这个方法为什么找不到声明的地方?按F12会调到委托类型CalculateHandler声明的地方。委托对象在编译时,由delegate和另一个来自MultiCastDelegate的密封类,共同维护这种操作,要想看到他的声明,用ildasm打开生成的exe,会发现有Invoke,BeginInvoke,EndInvoke的声明2.点击事件中第三句,calculateHandler.BeginInvoke()的最后一个参数传入的是委托实例自身,这样做有什么意义?最后一个参数本意是放异步回调的结果的,这里用了委托实例,指向Calculate方法,返回整型;再看异步回调委托CalculateCallBack的内部实现,若null返回,意思是还没有计算完a+b,则回调返回,继续计算,否则,执行其他操作