这里用一个简单的例子来演示 "异步调用" 和 "跨线程调用窗口控件"
假设您现在写了一个函数:
public DataTable GetPersonInfo (string personName)
{
//这是一个在数据库中找个人信息的方法
//内容怎么写,你喜欢
}
由于 GetPersonInfo 一下子可能会出来很多的结果,
如果不是异步调用的话,主界面很有可能卡卡的
所以这时候需要异步了!
首先,写一个委托代表 GetPersonInfo 这个方法:
delegate DataTable Del_GetPersonInfo(string personName) ;
然后,写一个回调的方法
void CallBack_GetPersonInfo(IAsyncResult ar)
{
Del_GetPersonInfo del=(Del_GetPersonInfo)ar.AsyncState ;
DataTable tab=del.EndInvoke(ar);
}
这个代码稍加解释:
1, IAsyncResult 是异步操作的接口
2, tab 所接收到的就是委托的返回值,您可以把这个值给别的东西,下面会有补充
好不容易写好了一个异步调用的方法,但是问题又来了
因为所得到的 tab 是另一条线程的结果,
如果要在主线程中的控件要用到这个结果,还要经过跨线程调用
比如说主窗口中有个 dataGridView1 的网格控件,
如果你把刚才的回调函数写成:
void CallBack_GetPersonInfo(IAsyncResult ar)
{
Del_GetPersonInfo del=(Del_GetPersonInfo)ar.AsyncState ;
dataGridView1.DataSource=del.EndInvoke(ar);//这里想直接调用另一条线程的结果
}
那么十有八九会报错说:跨线程什么什么不行的
解决把法是这样子的:
首先要写一个跨线程调用 dataGridView1 的委托:
delegate void Del_InvokeDGV(DataTable tab) ;
然后就写跨线程调用 dataGridView1 的方法:
void Call_DGV(DataTable tab)
{
if(this.dataGridView1.InvokeRequired)
{
Del_InvokeDGV del=new Del_InvokeDGV(Call_DGV);
this.BeginInvoke(del , new objecy[] {tab} ) ;
}
else
{
this.dataGridView1.DataSource=tab;
}
}
这样子的话,刚才的
void CallBack_GetPersonInfo(IAsyncResult ar)
{
Del_GetPersonInfo del=(Del_GetPersonInfo)ar.AsyncState ;
dataGridView1.DataSource=del.EndInvoke(ar);
}
就不会报错了
这时你就可以在主程序中异步执行查看个人信息的方法了
new AsyncCallBack(CallBack_GetPersonInfo),
del );
总结:如果细心看上面的例子的话,
会发现不管是异步调用查询信息的方法,还是跨线程调用控件,
都有一个共同的写法,那就是:
先写一个委托,然后写一个调用方法
还有一个提示:先写跨线程调用控件的代码,然后写异步调用的代码
上面只是为了说明例子所以顺序反了!
假设您现在写了一个函数:
public DataTable GetPersonInfo (string personName)
{
//这是一个在数据库中找个人信息的方法
//内容怎么写,你喜欢
}
由于 GetPersonInfo 一下子可能会出来很多的结果,
如果不是异步调用的话,主界面很有可能卡卡的
所以这时候需要异步了!
首先,写一个委托代表 GetPersonInfo 这个方法:
delegate DataTable Del_GetPersonInfo(string personName) ;
然后,写一个回调的方法
void CallBack_GetPersonInfo(IAsyncResult ar)
{
Del_GetPersonInfo del=(Del_GetPersonInfo)ar.AsyncState ;
DataTable tab=del.EndInvoke(ar);
}
这个代码稍加解释:
1, IAsyncResult 是异步操作的接口
2, tab 所接收到的就是委托的返回值,您可以把这个值给别的东西,下面会有补充
好不容易写好了一个异步调用的方法,但是问题又来了
因为所得到的 tab 是另一条线程的结果,
如果要在主线程中的控件要用到这个结果,还要经过跨线程调用
比如说主窗口中有个 dataGridView1 的网格控件,
如果你把刚才的回调函数写成:
void CallBack_GetPersonInfo(IAsyncResult ar)
{
Del_GetPersonInfo del=(Del_GetPersonInfo)ar.AsyncState ;
dataGridView1.DataSource=del.EndInvoke(ar);//这里想直接调用另一条线程的结果
}
那么十有八九会报错说:跨线程什么什么不行的
解决把法是这样子的:
首先要写一个跨线程调用 dataGridView1 的委托:
delegate void Del_InvokeDGV(DataTable tab) ;
然后就写跨线程调用 dataGridView1 的方法:
void Call_DGV(DataTable tab)
{
if(this.dataGridView1.InvokeRequired)
{
Del_InvokeDGV del=new Del_InvokeDGV(Call_DGV);
this.BeginInvoke(del , new objecy[] {tab} ) ;
}
else
{
this.dataGridView1.DataSource=tab;
}
}
这样子的话,刚才的
void CallBack_GetPersonInfo(IAsyncResult ar)
{
Del_GetPersonInfo del=(Del_GetPersonInfo)ar.AsyncState ;
dataGridView1.DataSource=del.EndInvoke(ar);
}
就不会报错了
这时你就可以在主程序中异步执行查看个人信息的方法了
Del_GetPersonInfo del=new Del_GetPersonInfo(GetPersonInfo);
new AsyncCallBack(CallBack_GetPersonInfo),
del );
总结:如果细心看上面的例子的话,
会发现不管是异步调用查询信息的方法,还是跨线程调用控件,
都有一个共同的写法,那就是:
先写一个委托,然后写一个调用方法
还有一个提示:先写跨线程调用控件的代码,然后写异步调用的代码
上面只是为了说明例子所以顺序反了!