You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows Forms中如何根据用户选择依次运行指定测量方法

Hey there! Let's break down your problem step by step—since you need sequential execution (no parallelism) and your longest measurement is only 10 seconds, threads are indeed overkill here. Let's fix the checkbox-to-method mapping first, then look at simpler, cleaner alternatives to threads.

1. Ditch Threads for Sequential Synchronous Execution (Simplest Solution)

Your current thread code with Join() already forces sequential execution, but creating and joining threads adds unnecessary overhead. Since you don't need parallelism, you can just call your methods directly in order. No threads required!

First, encapsulate each measurement's full workflow (sending the command + drawing the graph) into a single Action—this makes it easy to map to checkboxes later:

private readonly Measure _measurement = new Measure(); // Reuse one instance instead of creating new each time

// Encapsulate complete logic for each measurement
private void RunTetnienieMeasurement()
{
    _measurement.SendCommandToArduino("tetnienie");
    _measurement.DrawGraphTetnien(tetnienie_Chart);
}

private void RunJasnoscMeasurement()
{
    _measurement.SendCommandToArduino("jasnosc");
    // Add your graph drawing logic here if needed
}

// Add similar methods for your other 3 measurements

2. Map Checkboxes to Measurements (Clean, Maintainable Way)

Instead of hardcoding checks for each checkbox, create a dictionary that links each checkbox to its corresponding measurement action. This makes it easy to add/remove measurements later without rewriting core logic:

// Initialize this in your form's constructor or Load event
private Dictionary<CheckBox, Action> _checkboxToMeasurement = new Dictionary<CheckBox, Action>();

private void InitializeCheckboxMappings()
{
    _checkboxToMeasurement.Add(tetnienieCheckBox, RunTetnienieMeasurement);
    _checkboxToMeasurement.Add(jasnoscCheckBox, RunJasnoscMeasurement);
    // Add entries for your other 3 checkboxes and their matching methods
}

Then, in your "RUN" button's OnClick event:

private void RunButton_Click(object sender, EventArgs e)
{
    // Collect selected measurements in the order you defined in the dictionary
    var selectedMeasurements = _checkboxToMeasurement
        .Where(kvp => kvp.Key.Checked)
        .Select(kvp => kvp.Value)
        .ToList();

    // Execute each measurement one after another
    foreach (var measurementAction in selectedMeasurements)
    {
        measurementAction(); // Shorthand for measurementAction.Invoke()
    }

    MessageBox.Show("Done all measurements!");
}

If you prefer using your 5-bit string approach (e.g., "10011" means first, fourth, fifth measurements are selected), you can map each bit position to an action:

private List<Action> _bitPositionToMeasurement = new List<Action>
{
    RunTetnienieMeasurement, // Bit 0 (first character in the string)
    RunJasnoscMeasurement,    // Bit 1
    // Add the other 3 measurements in matching order
};

private void RunButton_Click(object sender, EventArgs e)
{
    string selectedBits = "10011"; // Replace with your actual 5-bit string generation logic
    for (int i = 0; i < selectedBits.Length; i++)
    {
        if (selectedBits[i] == '1')
        {
            _bitPositionToMeasurement[i]();
        }
    }

    MessageBox.Show("Done all measurements!");
}

3. Modern Alternatives (If You Want UI Responsiveness)

If you want to keep the UI responsive (so users can move the window or interact with other elements while measurements run), you can use async/await with Task.Run—this still maintains sequential execution but avoids freezing the UI:

private async void RunButton_Click(object sender, EventArgs e)
{
    runButton.Enabled = false; // Prevent accidental multiple clicks
    var selectedMeasurements = _checkboxToMeasurement
        .Where(kvp => kvp.Key.Checked)
        .Select(kvp => kvp.Value)
        .ToList();

    foreach (var action in selectedMeasurements)
    {
        // Run the measurement on a background thread, wait for it to finish before next
        await Task.Run(action);
    }

    MessageBox.Show("Done all measurements!");
    runButton.Enabled = true;
}

This is a better approach than manual threads if you need UI responsiveness, and it's far cleaner than managing thread creation/joining yourself.

4. Fixing Your Original Thread Code (For Reference)

If you really wanted to use threads (though it's unnecessary here), your original code had a mistake in the RunThread method—you can't pass a method name string to ThreadStart. Instead, pass the Action directly:

void RunThread(Action action)
{
    using (var thread = new Thread(new ThreadStart(action)))
    {
        thread.Start();
        thread.Join();
    }
}

// Then in your loop:
foreach (var action in measureToDo)
{
    RunThread(action);
}

But again, this is redundant for your use case since Join() forces sequential execution, making it equivalent to just calling the method directly.


To summarize:

  • Best approach: Use synchronous execution with checkbox-to-Action mapping for simplicity and no overhead.
  • If you need UI responsiveness: Use async/await with Task.Run to keep the UI alive while running sequential measurements.
  • Avoid manual threads: They add unnecessary complexity for your 10-second sequential tasks.

内容的提问来源于stack exchange,提问作者Kamil Turowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:03:21