螺纹内螺纹试图调用和更新UI [英] Thread inside thread trying to invoke and update ui

查看:152
本文介绍了螺纹内螺纹试图调用和更新UI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个文本框的WinForm和框TextChanged执行后台线程:

I have on winform with a textbox and on textchanged executes a background thread:

private void txtFathersLast_TextChanged(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(_ => WaitWhileUserTyping());
}
private void WaitWhileUserTyping()
        {
            var keepWaiting = true;

            while (keepWaiting)
            {
                _keyPressed = false;

                Thread.Sleep(TypingDelay);

                keepWaiting = _keyPressed;
            }

            Invoke((MethodInvoker)(ExecuteSearch));

            _waiting = false;
        }


private void ExecuteSearch()
        {
            Thread.Sleep(200);

            Task.Factory.StartNew(() =>
            {

                using (DataReference.SearchWCF search = new DataReference.SearchWCF())
                {
                    _similaritySearchResults = search.SearchPersonBySimilarity(txtFathersLast.Text, txtMothersLast.Text, txtName.Text, DateTime.Now, 10);
                }

            }).ContinueWith(t=>{

                if (this.InvokeRequired)
                {
                    this.BeginInvoke(new Action(() =>
                    {
                        if (_similaritySearchResults != null && _similaritySearchResults.Tables["data"].Rows.Count > 0)
                        {
                            DataTable dt = _similaritySearchResults.Tables["data"];

                            Infragistics.Win.Misc.UltraTile newTile = null;

                            for (int index = 0; index < dt.Rows.Count; index++)
                            {
                                newTile = new Infragistics.Win.Misc.UltraTile("Person X");
                                newTile.Control = new CustomControls.Controls.PersonResult("123", "123", index + 150);
                                newTile.Tag = new Guid("90D27721-7315-4B86-9CFD-4F7D02921E9A");
                                newTile.DoubleClick += TileDoubleClick;
                                tilePanel.Tiles.Add(newTile);
                            }
                        }

                    }));
                }
                else
                {
                    if (_similaritySearchResults != null && _similaritySearchResults.Tables["data"].Rows.Count > 0)
                    {
                        DataTable dt = _similaritySearchResults.Tables["data"];

                        Infragistics.Win.Misc.UltraTile newTile = null;

                        for (int index = 0; index < dt.Rows.Count; index++)
                        {
                            newTile = new Infragistics.Win.Misc.UltraTile("Person X");
                            newTile.Control = new CustomControls.Controls.PersonResult("123", "123", index + 150);
                            newTile.Tag = new Guid("90D27721-7315-4B86-9CFD-4F7D02921E9A");
                            newTile.DoubleClick += TileDoubleClick;
                            tilePanel.Tiles.Add(newTile);
                        }
                    }
                }




            }, TaskScheduler.FromCurrentSynchronizationContext());


        }

这是工作的罚款,该应用程序进入到一个数据库,然后得到的结果和更新用户界面,增加瓷砖的不同按数据库返回的记录数的控制。

This is working fine, the application goes to a database then get results and update the UI, adding tiles to a control depending of the number of records returned by database.

现在,问题是当我尝试添加另一个后台线程进入我的自定义控件:

Now, the problem comes when I try to add another background thread into my custom control:

新CustomControls.Controls.PersonResult(123,123,指数+ 150);

new CustomControls.Controls.PersonResult("123", "123", index + 150);

在code的控制是:

protected override void InitLayout()
        {
            // if I comment this then everything works fine
            // but if I leave this, then the UI freezes!!
            GetPictureAsync();

            base.InitLayout();
        }

/// <summary>
        /// 
        /// </summary>
        private void GetPictureAsync()
        {
            // This line needs to happen on the UI thread...
            TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();


            Task.Factory.StartNew(() =>
            {
                Random sleep = new Random();
                System.Threading.Thread.Sleep(sleep.Next(1000,3000));
                if (this.pbPhoto.InvokeRequired)
                {
                    this.pbPhoto.Invoke(new Action(() =>
                    {
                        this.Load(@"E:\Photos\" + PhotoId.ToString() + ".jpg");
                        //this.pbPhoto.Image = Utility.Common.GetResourceImage("woman_sample.jpg");
                    }));
                }
                else
                {
                    this.Load(@"E:\Photos\" + PhotoId.ToString() + ".jpg");
                    //this.pbPhoto.Image = Utility.Common.GetResourceImage("woman_sample.jpg");
                }


            }, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
        }

所以,问题似乎是我第一次执行一个线程希望何时开始搜索,那么该线程里面我为了获得数据库中的数据运行的另一个线程,然后在UI更新每个控制将运行另一个线程得到的图片和更新一个图片。

So the problem seems to be that I first execute a thread for looking when to start search, then inside that thread I run another thread in order to get data from database, and then each control updated in the UI will run another thread to get a picture and update a picturebox.

任何人知道如何解决这个问题?还是有办法来解决此问题?

Anyone knows how to solve this? or a way to work around this?

推荐答案

我觉得问题就出在你强迫任务 GetPictureAsync 来执行的UI线程,然后你呼吁 Thread.sleep代码()。这<一个href=\"http://stackoverflow.com/questions/17418208/update-ui-in-task-using-taskscheduler-fromcurrentsynchronizationcontext\">update如您在使用TaskScheduler.FromCurrentSynchronizationContext 问题UI在任务铲球同样的问题。我会重写你的code为:

I think the problem lies in you forcing the Task in GetPictureAsync to execute on UI thread and then you are calling Thread.Sleep(). This update UI in Task using TaskScheduler.FromCurrentSynchronizationContext question tackles the same problem as you are having. I would rewrite your code as:

private void async GetPictureAsync()
{
    Random sleep = new Random();
    await TaskEx.Delay(sleep.Next(1000,3000));
    this.Load(@"E:\Photos\" + PhotoId.ToString() + ".jpg");
}

这篇关于螺纹内螺纹试图调用和更新UI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆