【问题标题】:C# Accessing form control from different threadC#从不同线程访问表单控件
【发布时间】:2018-04-23 12:45:22
【问题描述】:

我很长一段时间以来一直在研究https://docs.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls 和其他 Stack Overflow 问题,现在想弄清楚如何使用线程安全方法从不同线程访问 ListView 控件。

以下是我想在我的程序中实现并行任务的方式: 我同时调用了四种不同的方法:

Parallel.Invoke(ProcessLow, ProcessMed, ProcessHigh, ProcessSprint);

每个方法都使用 for 循环搜索相同的 collection (data[i].Knots) 并在该 collection 内查找不同的值范围,然后如果其中一个方法在它正在查找的范围内找到适当的值因为它将时间和节(data[i].Timedata[i].Knots)添加到其各自的ListView(方法分别写入lstvLowlstvMedlstvHighlstvSprint)。目前它只是为非线程安全代码抛出异常。如果我有不同的线程只是读取同一个集合,它也会中断吗? (如果是这样,我该如何解决这个问题?)

tldr:并行处理对我来说是新事物,如何对 Windows 窗体控件进行线程安全调用。
如果可以的话,请向我指出除了 msdn 之外的一些好的阅读方向,用于并行任务。

编辑:这是winforms

【问题讨论】:

标签: c# multithreading winforms listview thread-safety


【解决方案1】:

进行线程安全调用。使用Control.Invoke(); 方法。假设您有 ListView mylistView; 的实例,您可以编写:

object result =  mylistView.Invoke(new Action(() => mylistView.DoSomething()));

【讨论】:

    【解决方案2】:

    据我了解,您是多任务处理的新手。我希望我的案例研究对你有所帮助。创建一个带有下一个控件的窗体:

    • startButton, stopButton 作为按钮
    • minTextEdit, maxTextEdit 作为文本编辑
    • listListView 作为列表视图

    对于 startButton 和 stopButton 使用适当的方法:startButton_ClickstopButton_Click

    填写下面的代码:

    using System;
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace Thread0
    {
        public partial class MainForm : Form
        {
            public MainForm()
            {
                InitializeComponent();
            }
    
            private static readonly Random _random = new Random();
            private List<int> lst = new List<int>();
            private bool isRun = false;
    
            private void startButton_Click(object sender, EventArgs e)
            {
                isRun = true;
                stopButton.Enabled = true;
                startButton.Enabled = false;
                var tskMain = Task.Run(() =>
                {
                    for (int i = 0; i < 8; i++)
                    {
                        var tsk1 = Task.Run(() =>
                        {
                            while (true)
                            {
                                int max = 0;
                                int min = Int32.MaxValue;
                                lock (lst)
                                {
                                    int num = _random.Next(1, 1000000);
                                    lst.Add(num);
                                    foreach (var x in lst)
                                    {
                                        if (x > max) max = x;
                                        if (min > x) min = x;
                                    }
                                    listListView.BeginInvoke(new Action(() => listListView.Items.Insert(0, num.ToString())));
                                }
                                maxTextBox.BeginInvoke(new Action(() => maxTextBox.Text = max.ToString()));
                                minTextBox.BeginInvoke(new Action(() => minTextBox.Text = min.ToString()));
    
                                if (!isRun) break;
    
                                Thread.Sleep(100);
                            }
                        });
                    }
                });
            }
    
            private void stopButton_Click(object sender, EventArgs e)
            {
                isRun = false;
                stopButton.Enabled = false;
                startButton.Enabled = true;
            }
        }
    }
    

    当您单击“开始”按钮时,流会创建并运行tskMain 线程,这会再创建 8 个线程。在它们中的每一个中,将一个整数添加到值列表lst,并搜索最大值和最小值。 listListView也加上了新的数字,最大值和最小值在对应的minTextEditmaxTextEdit中。

    在工作中使用 lambda 表达式很方便。

    lock(lst) ... 块使用值列表。一次一个动作,所以没有例外。

    BeginInvoke 方法允许您从线程调用主表单流中的表单元素的方法。 Action 用于将 lambda 表达式“转换”为委托方法。

    在每个线程内部,检查变量IsR​​un,如果其值为false,则线程执行停止。

    好吧,为了确保一切都不会很快使用.Sleep

    【讨论】:

    • 干杯!这很有帮助!
    猜你喜欢
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多