想把某个需要返回值的任务放到后台执行,避免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;
}
}
}

解决方案 »

  1.   

    endinvoke要等task执行玩了才返回。
    你begininvoke后马上endinvoke,有这样的用法嘛
      

  2.   

    // Define the method that receives a callback when the results are available.
            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();
           }
      

  3.   

    再包装一下:
    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;
            }
      

  4.   

    http://www.cnblogs.com/luminji/archive/2010/09/17/1829333.html
      

  5.   

    改成如下形式了,在BeginInvoke和EndInvoke中间加入的循环,
    循环中执行 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;
    } }
      

  6.   

    代码在这里,楼主参考
    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;
    }
    }
    }
      

  7.   

    有人告诉我BeginInvoke并不等于创建一个线程,你应该创建一个线程去做这个事情