想把某个需要返回值的任务放到后台执行,避免UI阻塞造成用户的不良感受,于是用了BeginInvoke和EndInvoke,结果发现仍然阻塞了UI。以下面的代码为例,应该怎样做可以让线程可以返回值并且不阻塞UI:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;namespace test_BeginInvoke
{
public partial class Form1 : Form
{
private delegate int TaskWork(); public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
TaskWork tsk1 = Work1;
IAsyncResult asyRst = tsk1.BeginInvoke(null, null);
int i = tsk1.EndInvoke(asyRst);
MessageBox.Show(i.ToString());
} private int Work1()
{
int k=1;
for (int i = 1; i <= 5; i++)
{
Thread.Sleep(1000);
MessageBox.Show(i.ToString());
k = k * i;
} return k;
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;namespace test_BeginInvoke
{
public partial class Form1 : Form
{
private delegate int TaskWork(); public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
TaskWork tsk1 = Work1;
IAsyncResult asyRst = tsk1.BeginInvoke(null, null);
int i = tsk1.EndInvoke(asyRst);
MessageBox.Show(i.ToString());
} private int Work1()
{
int k=1;
for (int i = 1; i <= 5; i++)
{
Thread.Sleep(1000);
MessageBox.Show(i.ToString());
k = k * i;
} return k;
}
}
}
解决方案 »
- 某个时间段倒计时问题?急急!!!
- [C# - WinForms] 如何让控件在非正常DPI(正常DPI=96)下不走位?
- 应用程序window2003下可以运行,xp下不行(xp安装了.netframework2.0的)
- 星星100分问asp/asp.net问题
- 各位,可不可以自己做一个在网站上即时聊天的东西,请大哥帮忙,救救不弟,要不然我就完了,求求各位了。
- 请高手帮我看段代码
- 在c#.net程序中,如果把一段文字保存成一幅图片? 多谢!!!
- 水晶报表中数字格式问题
- 谁有好的电脑图书下在网址啊!(100分)
- 请C#大虾们指点
- 请教FileStream缓存一定量再写入内存比直接写硬盘要慢
- 为什么没有死锁?
你begininvoke后马上endinvoke,有这样的用法嘛
public void FactorizedResults(IAsyncResult result)
{
int factor1=0;
int factor2=0; // Extract the delegate from the
// System.Runtime.Remoting.Messaging.AsyncResult.
AsyncFactorCaller factorDelegate = (AsyncFactorCaller)((AsyncResult)result).AsyncDelegate;
int number = (int) result.AsyncState;
// Obtain the result.
bool answer = factorDelegate.EndInvoke(ref factor1, ref factor2, result);
// Output the results.
Console.WriteLine("On CallBack: Factors of {0} : {1} {2} - {3}",
number, factor1, factor2, answer);
waiter.Set();
} // The following method demonstrates the asynchronous pattern using a callback method.
public void FactorizeNumberUsingCallback()
{
AsyncFactorCaller factorDelegate = new AsyncFactorCaller (PrimeFactorFinder.Factorize);
int number = 1000589023;
int temp=0;
// Waiter will keep the main application thread from
// ending before the callback completes because
// the main thread blocks until the waiter is signaled
// in the callback.
waiter = new ManualResetEvent(false); // Define the AsyncCallback delegate.
AsyncCallback callBack = new AsyncCallback(this.FactorizedResults); // Asynchronously invoke the Factorize method.
IAsyncResult result = factorDelegate.BeginInvoke(
number,
ref temp,
ref temp,
callBack,
number); // Do some other useful work while
// waiting for the asynchronous operation to complete. // When no more work can be done, wait.
waiter.WaitOne();
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(delegate
{
TaskWork tsk1 = Work1;
IAsyncResult asyRst = tsk1.BeginInvoke(null, null);
int i = tsk1.EndInvoke(asyRst);
MessageBox.Show(i.ToString());
}));
t.Start();
} private int Work1()
{
int k = 1;
for (int i = 1; i <= 5; i++)
{
Thread.Sleep(1000);
MessageBox.Show(i.ToString());
k = k * i;
} return k;
}
循环中执行 Sleep(100)和PrograssBar.Value= 中间变量nPrograss;
同时线程中也在不停的修改中间变量nPrograss;
这样确实可以在线程运行的过程中,改变进度条;
但是主线程UI仍然无法响应,也就是说,BeginInvoke和EndInvoke之间只能让UI线程执行确定的工作,而不能让UI线程处于空闲的等待响应的状态?这不是我想要的结果啊。using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;namespace test_BeginInvoke
{
public partial class Form1 : Form
{
private int nProgress = 0; public Form1()
{
InitializeComponent();
progressBar1.Maximum = 100;
progressBar1.Minimum = 0;
} private void button1_Click(object sender, EventArgs e)
{
TaskWork tsk1 = Work1;
IAsyncResult asyRst = tsk1.BeginInvoke(null, null); //Thread.Sleep(5000);
while (progressBar1.Value < progressBar1.Maximum)
{
Thread.Sleep(100);
progressBar1.Value = nProgress;
}
tsk1.EndInvoke(asyRst);
} private int Work1()
{
//dgPgbIncrease _dgPi = new dgPgbIncrease(PgbIncrease);
int k=1;
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(200);
nProgress = i;
//progressBar1.Invoke(_dgPi, null);
} return k;
} }
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;namespace test_BeginInvoke_CallBack
{
public partial class Form1 : Form
{
string result; //用于开启线程的委托
public delegate string FuncHandle(int data1, int data2);
FuncHandle fh; //用于在线程中操作控件的委托
public delegate void dgPgbIncrease();
public delegate void dgCloseForm();
Form2 frm2; public Form1()
{
InitializeComponent();
progressBar1.Maximum = 10;
progressBar1.Minimum = 0;
progressBar1.Value = 0;
} private void button1_Click(object sender, EventArgs e)
{
frm2 = new Form2(); fh = new FuncHandle(this.Foo);
AsyncCallback callback = new AsyncCallback(this.AsyncCallbackImpl);
fh.BeginInvoke(1, 3, callback, null);
progressBar1.Value = 0; //用模态窗口显示进度条,在不阻塞主线程UI的前提下,屏蔽用户操作
frm2.ShowDialog();
//模态窗口从其内部关闭后,从全局变量result取得异步线程返回值
MessageBox.Show(result);
} public void AsyncCallbackImpl(IAsyncResult ar)
{
//在回调函数中取返回值
result = fh.EndInvoke(ar);
} string Foo(int data1, int data2)
{
dgPgbIncrease dgPi=new dgPgbIncrease(frm2.PgbIncrease);
dgCloseForm dgCf = new dgCloseForm(frm2.FormClose); for (int i = 0; i < 10; i++)
{
Thread.Sleep(1000);
//线程内部按照任务进度改变进度条
frm2.progressBar1.Invoke(dgPi, null);
} //线程内部在任务完成后关闭模态窗口
frm2.Invoke(dgCf, null);
return " " + data1 + data2;
} public void PgbIncrease()
{
progressBar1.Value++;
} private void button2_Click(object sender, EventArgs e)
{
progressBar1.Value = 0;
}
}
}