在控件的SynchronizationContext后队列中丢弃除最后一个之外的其他内容

时间:2017-02-10 09:37:56

标签: c# user-interface synchronizationcontext

假设UI更新需要相当长的时间。例如,此虚拟标签需要1秒钟才能更改文本。

public class MyLabel : Label
{
    public override string Text
    {
        get { return base.Text; }
        set
        {
            Debug.WriteLine("Setting " + value);
            Thread.Sleep(1000);
            base.Text = value;
        }
    }
}

如果有多个任务想要更新它,那么这些帖子似乎已排队。

var UIContext = SynchronizationContext.Current;

for (int i = 0; i < 10; i++)
{
    Task.Factory.StartNew((id) =>
    {
        Debug.WriteLine(id);
        Thread.Sleep((int)id*100);
        UIContext.Post((label) =>
        {
            myLabel1.Text = label.ToString();
        }, id);
    }, i);
}

标签似乎收到帖子排队,标签最终收到它们,但在这个例子中,下一个会覆盖前一个,所以不需要处理前一个。理想情况下,我想忽略除最后一个之外的所有帖子。我可以看到排队的项目并将其删除吗?

1 个答案:

答案 0 :(得分:0)

我想我想错了方向。我没有处理SynchronizationContext队列,而是创建了自己的队列,它似乎按照我的预期工作。

public class MyLabel : Label
{
    SynchronizationContext UIContext;
    List<string> TextQueue;
    public MyLabel()
    {
        UIContext = SynchronizationContext.Current;
        TextQueue = new List<string>();
    }

    public override string Text
    {
        get { return base.Text; }
        set
        {
            Debug.WriteLine("Setting " + value);
            Thread.Sleep(1000);
            base.Text = value;
        }
    }

    public void QueueTextChange(string text)
    {
        Debug.WriteLine("Request: " + text);
        lock (TextQueue)
        {
            TextQueue.Add(text);
        }
        UIContext.Post((x) => { SetTextFromQueue();}, null);
    }

    void SetTextFromQueue()
    {
        string last=null;
        lock (TextQueue)
        {
            if (TextQueue.Count > 0)
            {
                last = TextQueue.Last();
                TextQueue.Clear();
            }
        }
        if (last != null)
            Text = last;
    }
}

其他线程不直接调用myLabel1.Text = "",而是调用特殊的排队方法,如下所示。

myLabel1.QueueTextChange(label.ToString());