首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模拟PostMessage

模拟PostMessage
EN

Stack Overflow用户
提问于 2015-01-15 15:28:56
回答 1查看 347关注 0票数 0

在常规WinAPI中,您可以使用PostMessage向应用程序内的窗口发送消息,它不会等待消息被处理,它会立即返回。

现在,在我的窗口中,我收到了这条消息,它在同一个UI线程中调用,我可以在这个线程中操作一些其他的UI控件。

如何在.NET WinForms中模拟此行为?

我知道我可以使用Delegate.BeginInvoke,它将异步调用我的方法,但它不会在同一个UI线程中执行,并且任何对UI控件的访问都会引发异常。我知道我可以使用Control.Invoke来改变该方法中的UI,但是编写代码太多了,我希望不用担心这一点,并以与WinAPI相同的方式工作。

我有这样一个代码

代码语言:javascript
复制
public delegate void DoDelegate();

        private DoDelegate d;

        public Form1()
        {
            InitializeComponent();

            d = new DoDelegate(Do);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            d.BeginInvoke(ar =>
                {
                    AsyncResult result = (AsyncResult)ar;
                    DoDelegate dd = (DoDelegate)result.AsyncDelegate;
                    dd.EndInvoke(ar);
                }, null);
        }


        public void Do()
        {
            Action a = () =>
                {
                    for (int i = 0; i < 10; i++)
                    {
                        label1.Text = "Item " + i;
                        Thread.Sleep(1000);
                    }
                };
            if (InvokeRequired)
                Invoke(a);
            else a();
        }

即使在单独的线程中被调用,它也会阻塞主线程。我知道为什么,因为我在整个方法上使用了Control.Invoke,并且我应该只在设置.Text属性时使用它,但同样,这太多了,很容易忘记use Invoke,然后所有的崩溃。

那么,基本上,我如何调用异步方法,这样在没有调用机制的情况下访问UI不会产生任何问题,就像我使用PostMessage所做的那样?

想法?

EN

回答 1

Stack Overflow用户

发布于 2015-01-15 17:03:52

我使用这个扩展方法:

代码语言:javascript
复制
public static void InvokeIfRequired(this Control control, Action action)
{
  if (control.InvokeRequired)
    control.Invoke(action);
  else
    action();
}

我在访问UI的任何多线程代码上使用它。在您的示例中,它将如下所示:

代码语言:javascript
复制
label1.InvokeIfRequired(() => { label1.Text = "Item " + i });

请注意,如果您广泛地将其用于对控件的单个更改,则使用扩展方法的重载可能是明智的,例如:

代码语言:javascript
复制
public static void InvokeIfRequired(this Control control, Action<Control> action)
{
  if (control.InvokeRequired)
    control.Invoke(new Action(() => action(control)));
  else
    action(control);
}

所以你可以这样做:

代码语言:javascript
复制
label1.InvokeIfRequired(x => { x.Text = "Item " + i });

不必重复对lambda表达式的控制

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27958569

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档