c# 异步委托的问题

lb520zw 2014-08-21 12:57:13
我看了资料都说异步委托是开启一个新线程去执行,这样的话主线程就会继续执行。不然,如果是同步执行的话,如果操作时间长,主线程会等待,造成的结果是界面停止响应。

但是我参照下面的连接,为什么执行第2,3,4段代码(都是异步委托),界面还是要等方法执行完了才有反应的。

我是创建了一个winform程序,添加了一个button,和一个textbox,把下面连接里面的main方法里面的代码移到button的click事件里面了,当我点击button后,界面就停止响应了,没办法在文本框里输入了,只能等方法执行完后才行。

这样的话异步和同步区别又在哪里呢?

http://www.2cto.com/kf/201007/52332.html

...全文
546 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
比如说你在子线程中什么正经事情也不干,只不过是把那16000毫秒的工作再次重新注册给主线程去执行,那么这种操作就是瞎耽误工夫。这肯定不如直接用同步顺序执行程序、只用主线程执行更好。如果只会这种编程,就别考虑什么子线程了。
  • 打赏
  • 举报
回复
真正影响主线程处理用户操作体验的,是主线程使用方式,而不是“是否使用了异步委托”。 比如说在地图上要显示800个地点标注和30个区域标注,这些东西需要访问服务器去取得各种配套数据,需要计算,最后需要花时间去绘制。那么绘制过程必定占用主线程(假设需要800毫秒),而主线程发起这个请求时使用子线程去开始处理,那么除了最后的绘制过程以外的其它操作(假设需要16000毫秒)就可以让主线程立刻抢占到CPU时间去处理用户操作了。
  • 打赏
  • 举报
回复
引用 楼主 lb520zw 的回复:
我看了资料都说异步委托是开启一个新线程去执行,这样的话主线程就会继续执行。不然,如果是同步执行的话,如果操作时间长,主线程会等待,造成的结果是界面停止响应。 .......... 这样的话异步和同步区别又在哪里呢?
没有功夫看你连接的文章。跟你澄清一下概念名词儿。 异步不代表着一定是多线程编程。异步只是一种编程模式,是说一个功能方法的注册签名类似
public void DoIt(string param1, int param2, Action<MyInfo> callback)
{
    ....
}
这样地,是先注册回调方法的。至于说回调方法callback是不是在调用线程上被调用,那是不确定的。 把异步跟多线程(子线程)等同起来,严格意义上说是错误的。 异步处理,固然“暗示着”其回调方法可能在另一个线程上调用,但是也可能不是。因此你不能见到异步,就说人家有子线程。
  • 打赏
  • 举报
回复

System.Threading.ThreadPool.QueueUserWorkItem(
                 new System.Threading.WaitCallback(一些长期任务));

        private void 一些长期任务(Object state)
         {
             // 插入代码来执行一项艰巨的任务。

            int aa = 100;
             do
             {
                 System.Threading.Thread.Sleep(1000);
                 this.Invoke(new Action(() => { resultLabel.Text = (int.Parse(resultLabel.Text) + 1).ToString(); }));
             } while (--aa > 0);
         }

  • 打赏
  • 举报
回复
lb520zw 2014-08-22
  • 打赏
  • 举报
回复
楼上的,能否把你最后的进度条,是否阻塞得的代码贴出来,我想看明白点,你这个未阻塞用到winform的backgroundworker吗?
lb520zw 2014-08-21
  • 打赏
  • 举报
回复
回复1楼,代码请看这个连接 http://www.2cto.com/kf/201007/52332.html
漫天雪飞 2014-08-21
  • 打赏
  • 举报
回复
用backgroundWorker,这个可以让界面不在假死
gucangen 2014-08-21
  • 打赏
  • 举报
回复

以上测试一个堵塞,一个未堵塞;
说白堵塞是一个函数只能一个跑完跑另外一个;不堵塞是跑的时候另外一个也在跑;
其实你不用去管同步异步,只要知道这个效果只能异步能搞出来就行了;同步可以忽略不计,个人观点
gucangen 2014-08-21
  • 打赏
  • 举报
回复
我这个靠谱不?
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{

}

#region 主线程直接调用
private void button6_Click(object sender, EventArgs e)
{
if (Thread.CurrentThread.Name != "Main")
{
Thread.CurrentThread.Name = "Main";
}
TestInvoke();//同步
TestBeginInvoke();//异步
TestInvokeBeginInvoke();//先同步再异步
TestBeginInvokeInvoke();//先异步再同步
TestBeginInvokeEndInvoke();//结束异步;
}
/// <summary>
/// 从输出结果上可以看出,Invoke被调用后,是马上执行的。这点很好理解。
/// </summary>
private void TestInvoke()
{
listBox1.Items.Add("--开始同步调用测试--1");
listBox1.Items.Add("--begin--");
listBox1.Invoke(new Action(() =>//语1
{
Thread.Sleep(3000);
listBox1.Items.Add("Invoke:" + Thread.CurrentThread.Name);
}));
listBox1.Items.Add("--end----------------");
Thread.Sleep(1000);//主程序的sleep将会使得整个线程停止;
}
//<summary>
//从输出能看出,只有当调用BeginInvoke的线程结束后,才执行它的内容。
//</summary>
private void TestBeginInvoke()
{
listBox1.Items.Add("--开始异步调用测试--2");
listBox1.Items.Add("--begin--");
//listBox1.BeginInvoke(new Action(() =>
listBox1.BeginInvoke(new MethodInvoker(delegate//语2
{
Thread.Sleep(1000);//调用的时候需要等待的时间,异步是指CPU自己有空闲的时候合理分配空间给予执行;跟此时间无关;
listBox1.Items.Add("BeginInvoke1:" + Thread.CurrentThread.Name);
}));
listBox1.Items.Add("--end----------------");
}
private void TestInvokeBeginInvoke()
{
listBox1.Items.Add("--开始先同步后异步调用测试--3");
listBox1.Items.Add("--begin--");
//listBox1.Invoke(new Action(() =>
listBox1.Invoke((EventHandler)delegate//语3
{
listBox1.Items.Add("Invoke:" + Thread.CurrentThread.Name);//一运行到这里,其实把上一个函数的睡着的异步给弄醒了
});
listBox1.BeginInvoke(new Action(() =>
{
Thread.Sleep(3000);
listBox1.Items.Add("BeginInvoke2:" + Thread.CurrentThread.Name);
}));
listBox1.Items.Add("--end-------------------");
}
//<summary>
//不过有两种情况下,它会马上执行:
//调用BeginInvoke、Invoke
//同一个控件调用Invoke时,会马上执行先前的BeginInvoke
//</summary>
private void TestBeginInvokeInvoke()
{
listBox1.Items.Add("--开始先异步再同步调用测试--4");
listBox1.Items.Add("--begin--");
listBox1.BeginInvoke(new Action(() =>
{
Thread.Sleep(3000);
listBox1.Items.Add("BeginInvoke3:" + Thread.CurrentThread.Name);
}));
listBox1.Invoke(new Action(() =>
{
listBox1.Items.Add("Invoke:" + Thread.CurrentThread.Name);
}));
listBox1.Items.Add("--end-----------------------");
}
// <summary>
// 调用BeginInvoke、EndInvoke
//使用EndInvoke,检索由传递的 IAsyncResult 表示的异步操作的返回值。
// </summary>
private void TestBeginInvokeEndInvoke()
{
listBox1.Items.Add("--开始停止异步调用---------5");
listBox1.Items.Add("--begin--");
IAsyncResult bi = listBox1.BeginInvoke(new Action(() =>
{
Thread.Sleep(3000);
listBox1.Items.Add("BeginInvokeEndInvoke4:" + Thread.CurrentThread.Name);
}));
listBox1.EndInvoke(bi);
listBox1.Items.Add("--end----------------------");
}
//1、函数一个一个执行,或者集体执行,分别看运行结果,其中集体运行的时候几个异步均是被下一个函数的同步给唤醒的而进行立刻执行;
//2、异步调用前的sleep(5000)指的是(要运行异步的时候)需要等待主线程睡觉的时间,而不是指等待了这个(主线程睡觉的时间或者说是主线程运行了超过5秒后)会进行异步操作;
//整个线程的sleep,停止的包含了同步,异步,因为他们本身就是在主线程上执行;而跟是否是同异步无关
//3、对于方法一(new Action(() =>,方法二(new MethodInvoker(delegate,方法三(EventHandler)delegate语法不一样,结果一样,因为本质是一样;都是调用委托,只不过把委托函数体直接放在里面,没提出来;
//既然都是调用委托,那么直接提不出不就很清楚了,非得这样搞,所谓幽灵代码,无聊才搞的事情,代码是让人看得懂可维护,而不是背语法,让别人看不懂;
//如果说线程起的太多影响性能,使用线程池来解决,这个靠谱;但幽灵,匿名委托线程,太扯,闲的啊,没意义;
gucangen 2014-08-21
  • 打赏
  • 举报
回复
我这个全能跑,看我这个去理解同步异步吧;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{

}

#region 主线程直接调用
private void button6_Click(object sender, EventArgs e)
{
if (Thread.CurrentThread.Name != "Main")
{
Thread.CurrentThread.Name = "Main";
}
TestInvoke();//同步
TestBeginInvoke();//异步
TestInvokeBeginInvoke();//先同步再异步
TestBeginInvokeInvoke();//先异步再同步
TestBeginInvokeEndInvoke();//结束异步;
}
/// <summary>
/// 从输出结果上可以看出,Invoke被调用后,是马上执行的。这点很好理解。
/// </summary>
private void TestInvoke()
{
listBox1.Items.Add("--开始同步调用测试--1");
listBox1.Items.Add("--begin--");
listBox1.Invoke(new Action(() =>//语1
{
Thread.Sleep(3000);
listBox1.Items.Add("Invoke:" + Thread.CurrentThread.Name);
}));
listBox1.Items.Add("--end----------------");
Thread.Sleep(1000);//主程序的sleep将会使得整个线程停止;
}
//<summary>
//从输出能看出,只有当调用BeginInvoke的线程结束后,才执行它的内容。
//</summary>
private void TestBeginInvoke()
{
listBox1.Items.Add("--开始异步调用测试--2");
listBox1.Items.Add("--begin--");
//listBox1.BeginInvoke(new Action(() =>
listBox1.BeginInvoke(new MethodInvoker(delegate//语2
{
Thread.Sleep(1000);//调用的时候需要等待的时间,异步是指CPU自己有空闲的时候合理分配空间给予执行;跟此时间无关;
listBox1.Items.Add("BeginInvoke1:" + Thread.CurrentThread.Name);
}));
listBox1.Items.Add("--end----------------");
}
private void TestInvokeBeginInvoke()
{
listBox1.Items.Add("--开始先同步后异步调用测试--3");
listBox1.Items.Add("--begin--");
//listBox1.Invoke(new Action(() =>
listBox1.Invoke((EventHandler)delegate//语3
{
listBox1.Items.Add("Invoke:" + Thread.CurrentThread.Name);//一运行到这里,其实把上一个函数的睡着的异步给弄醒了
});
listBox1.BeginInvoke(new Action(() =>
{
Thread.Sleep(3000);
listBox1.Items.Add("BeginInvoke2:" + Thread.CurrentThread.Name);
}));
listBox1.Items.Add("--end-------------------");
}
//<summary>
//不过有两种情况下,它会马上执行:
//调用BeginInvoke、Invoke
//同一个控件调用Invoke时,会马上执行先前的BeginInvoke
//</summary>
private void TestBeginInvokeInvoke()
{
listBox1.Items.Add("--开始先异步再同步调用测试--4");
listBox1.Items.Add("--begin--");
listBox1.BeginInvoke(new Action(() =>
{
Thread.Sleep(3000);
listBox1.Items.Add("BeginInvoke3:" + Thread.CurrentThread.Name);
}));
listBox1.Invoke(new Action(() =>
{
listBox1.Items.Add("Invoke:" + Thread.CurrentThread.Name);
}));
listBox1.Items.Add("--end-----------------------");
}
// <summary>
// 调用BeginInvoke、EndInvoke
//使用EndInvoke,检索由传递的 IAsyncResult 表示的异步操作的返回值。
// </summary>
private void TestBeginInvokeEndInvoke()
{
listBox1.Items.Add("--开始停止异步调用---------5");
listBox1.Items.Add("--begin--");
IAsyncResult bi = listBox1.BeginInvoke(new Action(() =>
{
Thread.Sleep(3000);
listBox1.Items.Add("BeginInvokeEndInvoke4:" + Thread.CurrentThread.Name);
}));
listBox1.EndInvoke(bi);
listBox1.Items.Add("--end----------------------");
}
//1、函数一个一个执行,或者集体执行,分别看运行结果,其中集体运行的时候几个异步均是被下一个函数的同步给唤醒的而进行立刻执行;
//2、异步调用前的sleep(5000)指的是(要运行异步的时候)需要等待主线程睡觉的时间,而不是指等待了这个(主线程睡觉的时间或者说是主线程运行了超过5秒后)会进行异步操作;
//整个线程的sleep,停止的包含了同步,异步,因为他们本身就是在主线程上执行;而跟是否是同异步无关
//3、对于方法一(new Action(() =>,方法二(new MethodInvoker(delegate,方法三(EventHandler)delegate语法不一样,结果一样,因为本质是一样;都是调用委托,只不过把委托函数体直接放在里面,没提出来;
//既然都是调用委托,那么直接提不出不就很清楚了,非得这样搞,所谓幽灵代码,无聊才搞的事情,代码是让人看得懂可维护,而不是背语法,让别人看不懂;
//如果说线程起的太多影响性能,使用线程池来解决,这个靠谱;但幽灵,匿名委托线程,太扯,闲的啊,没意义;
dongdongdongJL 2014-08-21
  • 打赏
  • 举报
回复
sample: delegate void Method(); class Program { public static void Main() { Method aa = function; aa.beginInvoke( callback); doOther(); } void callback(AsynCallback aa) { aa.endInvoke(); }
Saleayas 2014-08-21
  • 打赏
  • 举报
回复
人家的代码只是一个演示。 这里演示的异步是,那个方法可以立即返回,然后你可以做其他的。 这里作者描述的异步只是针对那一个方法。 其他的代码都不是。 而你期望异步是整体的,包括了后续的方法。
zhouzangood 2014-08-21
  • 打赏
  • 举报
回复
  • 打赏
  • 举报
回复
关注一下
nongfuxu 2014-08-21
  • 打赏
  • 举报
回复
异步委托是什么? 是指beginInvoke嘛
threenewbee 2014-08-21
  • 打赏
  • 举报
回复
贴出你的代码。 你的异步代码中有没有加锁?

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧