1

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:

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

The code for the control is:

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);
        }

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?

svick
  • 236,525
  • 50
  • 385
  • 514
VAAA
  • 14,531
  • 28
  • 130
  • 253

2 Answers2

0

When you call

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

Is "123" a literal string, or are they being read from UI controls. For example,

new CustomControls.Controls.PersonResult(txtFathersName.Text", txtMothersName.Text, index + 150)

i cant test it right now, but isnt accessing the Text property not allowed from a thread other than the one that created the control?

Stuart
  • 267
  • 1
  • 5
  • 15
0

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");
}
Community
  • 1
  • 1
Anupam
  • 870
  • 4
  • 9
  • 19