简体   繁体   English

等待Parallel.ForEach时实时更新Winforms UI

[英]Updating Winforms UI in real time while waiting for a Parallel.ForEach

The below code does not work in 'real time'. 以下代码无法“实时”运行。 The intention is, when the button is clicked, validate a set of data on the background thread. 目的是当单击按钮时,在后台线程上验证一组数据。 I cannot allow true 'submission' until all of the data is validated, but I do want the textbox to update in real time. 在验证所有数据之前,我不允许真正的“提交”,但我确实希望文本框实时更新。

Instead, the textbox gets updated with the odd numbers, all at once. 取而代之的是,文本框一次更新为奇数。

I imagine what is happening is that the task.Wait is blocking the observable since I am observing on the main thread, but I cannot see a way around this as I need to update on the main thread. 我想象发生的事情是该任务。等待正在阻塞可观察对象,因为我正在主线程上进行观察,但是由于需要在主线程上进行更新,因此我看不到解决方法。

(Obviously this is just a proof of concept) (显然,这只是概念证明)

Somewhat related note - is this code guaranteed to threadsafe? 相关说明-此代码是否保证线程安全? Thanks. 谢谢。

private Subject<int> _subject; 
    public Form1()
    {
        InitializeComponent();
    }

    private int sleep = 2000;
    private int i = 0;
    private void LongRunningValidation(int num)
    {
        if (num % 2 == 0) return;

        Thread.Sleep(sleep * (i++));

        _subject.OnNext(num);
    }


    private ConcurrentBag<int> _bag;
    private void simpleButton1_Click(object sender, EventArgs e)
    {
        _subject = new Subject<int>();
        _subject.SubscribeOn(Scheduler.TaskPool).ObserveOn(SynchronizationContext.Current).Synchronize().Subscribe(UpdateTextBox);

        _bag = new ConcurrentBag<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        if(Validate())
        {
            //submit
        }
    }

    private bool Validate()
    {
        var task = Task.Factory.StartNew(StartValidationAsync);

        task.Wait();

        return true;
    }

    private void StartValidationAsync()
    {
        Parallel.ForEach(_bag, LongRunningValidation);
    }

    private void UpdateTextBox(int i)
    {
        textEdit1.Text = textEdit1.Text + "," + i;

    }
}

Your Validate method not async and as you say block main thread. 您的Validate方法不是异步的,正如您所说的阻止主线程。 Try use events: 尝试使用事件:

public delegate void ValidatedHandler(bool validate);
public event ValidatedHandler Validated;

private void Validate()
    {
        var task = Task.Factory.StartNew(StartValidationAsync);

        if (Validated != null)
           Validated(true);
    }

And subscribe on event: 并订阅活动:

private void simpleButton1_Click(object sender, EventArgs e)
{
    _subject = new Subject<int>();
     _subject.SubscribeOn(Scheduler.TaskPool).ObserveOn(SynchronizationContext.Current).Synchronize().Subscribe(UpdateTextBox);

_bag = new ConcurrentBag<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

this.Validated += OnValidated;
}


public void OnValidated(bool validate)
{
        if(validate)
        {
            //submit
        }
}

Windows Forms does not automatically update the UI, even if you are running a background thread. Windows Forms不会自动更新UI,即使您正在运行后台线程。 Try calling Update() on whatever you want to update. 尝试对要更新的任何内容调用Update()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM