【问题标题】:Showing/hiding label by another thread由另一个线程显示/隐藏标签
【发布时间】:2015-03-25 20:26:03
【问题描述】:

Someting 在我的代码中不起作用,所以我想问问是否有人可以帮助我。到目前为止我有这个:

private void searchList_TextChanged(object sender, EventArgs e)
    {
            Thread th = new Thread(new ThreadStart(setLabel));
            th.IsBackground = true;
            th.Start();

            //some code that needs time
  if (searchBox.Text == String.Empty)
        {
            listViewType.Items.Clear();
            fillListView();
        }

        else
        {

            listViewType.Items.Clear();
            var matchings = stringTypes.FindAll(delegate(string s) { return s.StartsWith(searchBox.Text); });

            for (int i = 0; i < matchings.Count; i++)
            {
                ListViewItem storeMatched = new ListViewItem(matchings[i]);
                storeMatched.SubItems.Add(matchings[i]);
                listViewType.Items.Add(storeMatched);

            }

            th.Abort();
            searchLabel.Visible = false;
}

     private void setLabel()
    {
        MethodInvoker set = () => searchLabel.Visible = true;
        searchLabel.BeginInvoke(set);
    }

所以 searchLabel 是我想要显示/隐藏的标签。我在这里尝试在操作开始之前显示标签并在完成后隐藏它。不知何故,它在代码执行后显示(//一些需要时间的代码)然后保持可见。如何正确编码?

【问题讨论】:

  • 整个过程我不清楚。将“需要时间的代码”放到后台线程似乎更合乎逻辑。在 UI 线程(或主线程)中,您应该轻松更改标签的可见状态。之后,只需在后台线程中调用 Visible 状态为 True 即可。
  • 我想那样做。可能吗?我现在尝试了“调用”,但还是一样
  • 看看下面我的回答

标签: c# multithreading winforms


【解决方案1】:
private void searchList_TextChanged(object sender, EventArgs e)
{
    searchLabel.Visible = false;
    backgroundWorker.RunWorkerAsync();
}

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    //some code that needs time
    Thread.Sleep(1000);
}

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    SetLabelVisible(true);
}

private delegate void SetLabelVisibleDelegate(bool status);

private void SetLabelVisible(bool status)
{
    if (searchLabel.InvokeRequired)
        searchLabel.Invoke(new SetLabelVisibleDelegate(SetLabelVisible), status);
    else
        searchLabel.Visible = status;
}

【讨论】:

  • 不知何故他不想启动“doWork”方法。它永远不会到达。
  • @ScorpX 您应该通过 VS Designer 添加 BackgroundWorker 控件,然后自动生成两个事件处理程序子例程:DoWork 和 RunWorkerCompleted
  • 是的,就是这样。非常感谢! :) 我仍然会尝试其他答案。
  • 好的。他仍然不想启动 doWork 方法。我创建了一个新工人并将所有内容与方法联系起来。
  • @ScorpX 这可能是因为新添加的工人曾经被命名为“backgroundWorker1”而我上面的一个是“backgroundWorker”:)
【解决方案2】:

您正在处理 UI 线程

你的

//some code that needs time

将挂起 UI 线程因此不会重新绘制,你应该使用新的 async / await 东西

Task.Run 可能不适合您的情况,但我需要更多地了解“一些代码”。

private async void searchList_TextChanged(object sender, EventArgs e)
{
    searchLabel.Visible = true;

    await Task.Run(() =>
    {
        // code that needs time 
    });

    // simulate
    await Task.Delay(5000);

    searchLabel.Visible = false;
}

【讨论】:

  • “一些代码”只是在 ListView 中搜索。所以它接受文本框输入,清除列表视图,在列表中搜索子字符串,将匹配的字符串放入新列表中,然后用这些字符串填充 ListView 并显示它们。
  • 这应该没问题,确保不要在非 UI 线程上操作列表视图。用延迟试试上面的代码,你会发现它有效。
  • 他需要很长时间才能加载……比平时要长得多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-22
相关资源
最近更新 更多