简体   繁体   中英

Multithreading on one WPF Window

I'm new to .net and i'm trying to apply two threads on one window

The application contains two buttons (start and stop) and one read only textbox when the user click on start the program will read from the com port and append it to the textbox and when click on stop it will stop. The problem is whenever i click on start the program stuck

only to make it shorter here i used "Hello World!".

C# code:

using System;
using System.Windows;
using System.Threading;

namespace ThreadingTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    private bool _continue = false;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void startWrite(object sender, RoutedEventArgs e)
    {
        startButton.IsEnabled = false;
        stopButton.IsEnabled = true;
        _continue = true;
        Dispatcher.Invoke((Action)(() =>
        {
            Hello();
        }));
    }

    private void stopWrite(object sender, RoutedEventArgs e)
    {
        startButton.IsEnabled = true;
        stopButton.IsEnabled = false;
        _continue = false;
    }

    public void Hello()
    {
        while (_continue)
        {
            HelloText.AppendText("Hello World!\n");
            //_continue = false;
        }
    }
}
}

xaml code:

<Window x:Class="ThreadingTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="296" Width="301"
    Background="WhiteSmoke">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="245*" />
        <RowDefinition Height="12*" />
    </Grid.RowDefinitions>
    <TextBox Name="HelloText"
             IsReadOnly="True"
             HorizontalAlignment="Left"
             Margin="12,12,0,0"
             VerticalAlignment="Top"
             Height="233"
             Width="174" />
    <Button Name="startButton"
            IsEnabled="True"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Height="25"
            Width="50"
            Margin="208,12,0,0"
            Content="Start"
            Click="startWrite" />
    <Button Name="stopButton"
            IsEnabled="False"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Height="25"
            Width="50"
            Margin="208,45,0,0"
            Content="Stop"
            Click="stopWrite" />
</Grid>
</Window>

and sorry for my English

You should use BackgroundWorker ( msdn ).

Example:

public partial class MainWindow : Window
{
    private bool _continue = false;

    public MainWindow()
    {
        InitializeComponent();

        worker.WorkerSupportsCancellation = true;
        worker.DoWork += delegate 
        {
            Hello();
        };
    }

    BackgroundWorker worker = new BackgroundWorker();

    private void startWrite(object sender, RoutedEventArgs e)
    {
        startButton.IsEnabled = false;
        stopButton.IsEnabled = true;
        _continue = true;
        worker.RunWorkerAsync();
    }

    private void stopWrite(object sender, RoutedEventArgs e)
    {
        worker.CancelAsync();
        startButton.IsEnabled = true;
        stopButton.IsEnabled = false;
        _continue = false;
    }

    public void Hello()
    {
        while (_continue)
        {
            Application.Current.Dispatcher.Invoke((Action)(() =>
            {
                HelloText.AppendText("Hello World!\n");
            }));                
        }
    }
}

Simple ... with
Dispatcher.Invoke((Action)(() => { Hello(); }));

you invoke this loop again back in the WPF Dispatcher Thread so you !Don't! use multithreding

My advice... inform yourself more about threads, callbacks and Tasks in C# at all and than start to use it in WPF

You don't need to "apply two threads on one window"...

You have your UI-Thread, and you need a second thread to get data from the com port and send it to your UI-Thread.

You can use for example the BackgroundWorker Class. And send the data via an additional event to the UI-Thread, where you catch the fired event and append the sent data to your textbox.

If you're going to perform any long running task which can be done in the background I suggest you take a look at the BackgroundWorker class.

Otherwise you might want to take a look at the Task and TaskFactory classes for less complex work (and code).

Here is the simplest approach:

private void startWrite(object sender, RoutedEventArgs e)
{
    startButton.IsEnabled = false;
    stopButton.IsEnabled = true;
    _continue = true;
    Thread myThread = new Thread(startWriteThread);
    startWriteThread.Start();
}

private void startWriteThread()
{
    Hello();
}

I do, however, recommend you to follow the recommendations as suggested by @Jurgen Camilleri, since it is a cleaner approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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