我在winform上使用文本框,在textchanged上执行后台线程:
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());
}
这很好用,应用程序转到数据库然后获取结果并更新UI,根据数据库返回的记录数量向控件添加切片。
现在,当我尝试将另一个后台线程添加到我的自定义控件中时,问题出现了:
new CustomControls.Controls.PersonResult(“123”,“123”,index + 150);
控件的代码是:
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中更新的每个控件将运行另一个线程获取图片并更新图片框。
任何人都知道如何解决这个问题?或解决这个问题的方法?
答案 0 :(得分:0)
致电时
new CustomControls.Controls.PersonResult("123", "123", index + 150)
“123”是文字字符串,还是从UI控件中读取。例如,
new CustomControls.Controls.PersonResult(txtFathersName.Text", txtMothersName.Text, index + 150)
我现在无法测试它,但是不能从创建控件的线程以外的线程访问Text属性吗?
答案 1 :(得分:0)
我认为问题在于你强迫GetPictureAsync
中的任务在UI线程上执行,然后你正在调用Thread.Sleep()
。这个update UI in Task using TaskScheduler.FromCurrentSynchronizationContext问题可以解决您遇到的同样问题。我会将您的代码重写为:
private void async GetPictureAsync()
{
Random sleep = new Random();
await TaskEx.Delay(sleep.Next(1000,3000));
this.Load(@"E:\Photos\" + PhotoId.ToString() + ".jpg");
}