C++\CLI ThreadStart - multithreading

I was reading a tutorial about multi-threading. However, the tutorial is written in C#. My application, unfortunately, is written in C++\CLI. I would like to know the equivalent code in C++\CLI of the following C# code:
private void button1_Click(object sender, EventArgs e)
{
Thread backgroundThread = new Thread(
new ThreadStart(() =>
{
Thread.Sleep(5000);
MessageBox.Show("Thread completed!");
}
));
backgroundThread.Start();
}
This C# code uses LINQ, which confuses me (I'm new to programming).
Update: I want to make a progress bar that can show the progress of the calculation of a huge loop, which calculates combinations. The application is frozen when calculating the loop, and that's why I need multi-threading.
Thanks in advance.

The equivalent C++/CLI code is the following:
void WorkCompleted()
{
Thread::Sleep(5000);
MessageBox::Show("Thread completed!");
}
void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
Thread^ backgroundThread = gcnew Thread(gcnew ThreadStart(this, &Form1::WorkCompleted));
backgroundThread->Start();
}

Related

An object reference is required for the non-static field method or property/field initializer cannot reference the non-static field method or property

I was making a program and I stumbled across this two-in-one problem, where the first problem leads to the other. I have not yet found a question where someone had both problems leading into eachother. I'm still learing, and have learned a lot from other problems I had, but I can't find a solution to this problem.
It has to do with threading. I want to make a thread, that can place something in a rich textbox every second or so, while I can still press buttons to start and stop it. But to make a function that a thread can run, I need to make the function static. Otherwise I'll get the error "A field initializer cannot reference the non-static field, method, or property". But when a function is static, it cannot acces any of the created items, like richTextBox1. Because if I try to change it's text, I get the error "Error 1 An object reference is required for the non-static field, method, or property". And if I fix this by removing static, the thread will not work.
I made a demo program that is smaller than the full one, but has the same problem. Button1 is the button to start the thread, Button2 is the one to stop it.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace threading_non_static_problem_demo
{
public partial class Form1 : Form
{
static Thread thr = new Thread(new ThreadStart(demofunc));
int checkthr = 0; //int to check if the thread has been running before (I like to do things like this)
int ifthrrun = 0; //int to check if the thread is running
public Form1()
{
InitializeComponent();
button2.Enabled = false; // so you can't click the "stop" button if nothing is running
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
static void demofunc()
{
while (true)
{
Thread.Sleep(1000);
richTextBox1.Text = richTextBox1.Text + "text added"; // <-- here's the problem
MessageBox.Show("tried to add text"); // you can use this messagebox to check if the thread is working correctly
}
}
private void button1_Click(object sender, EventArgs e)
{
if (checkthr == 0) // check if the thread has run before, 0 is no, 1 is yes, and then start or resume it
{
thr.Start();
ifthrrun = 1;
button2.Enabled = true;
button1.Enabled = false;
}
else if (checkthr == 1)
{
thr.Resume();
ifthrrun = 1;
button2.Enabled = true;
button1.Enabled = false;
}
}
private void button2_Click(object sender, EventArgs e)
{
thr.Suspend();
checkthr = 1;
ifthrrun = 0;
button2.Enabled = false;
button1.Enabled = true;
}
protected override void OnFormClosing(FormClosingEventArgs e) // if the program is closing, check the thread's state and act accordingly
{
if (ifthrrun == 0)
{
if (checkthr == 1)
{
thr.Resume();
thr.Abort();
}
else if (checkthr == 0)
{
}
}
else if (ifthrrun == 1)
{
thr.Abort();
}
}
}
}
To use this code just creat a forms application, add two buttons, and a rich text box, it should work.
Thank you in advance for you answers.
But to make a function that a thread can run, I need to make the
function static.
Get rid of the static declarations and move initialization of your "thr" variable to the constructor like this:
Thread thr;
public Form1()
{
InitializeComponent();
button2.Enabled = false; // so you can't click the "stop" button if nothing is running
thr = new Thread(new ThreadStart(demofunc));
Control.CheckForIllegalCrossThreadCalls = false;
}
private void demofunc()
{
while (true)
{
Thread.Sleep(1000);
richTextBox1.Text = richTextBox1.Text + "text added"; // <-- problem "solved" by disabling Control.CheckForIllegalCrossThreadCalls
}
}
But ignore the above "fix" because using Suspend()/Resume() is not recommended.
See Pausing and Resuming Threads:
Important
Starting with the .NET Framework version 2.0, the Thread.Suspend and
Thread.Resume methods are marked obsolete and will be removed in a
future release.
The Thread.Suspend and Thread.Resume methods are not
generally useful for applications and should not be confused with
synchronization mechanisms. Because Thread.Suspend and Thread.Resume
do not rely on the cooperation of the thread being controlled, they
are highly intrusive and can result in serious application problems
like deadlocks (for example, if you suspend a thread that holds a
resource that another thread will need).
One way to be able to pause/resume your loop would be to use a ManualResetEvent like this:
Thread thr;
ManualResetEvent mre = new ManualResetEvent(false);
public Form1()
{
InitializeComponent();
button2.Enabled = false; // so you can't click the "stop" button if nothing is running
thr = new Thread(new ThreadStart(demofunc));
}
private void demofunc()
{
while (!this.IsDisposed && !this.Disposing)
{
Thread.Sleep(1000);
if (!this.IsDisposed && !this.Disposing)
{
this.Invoke((MethodInvoker)delegate {
richTextBox1.AppendText("text added");
});
}
mre.WaitOne();
}
}
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
mre.Set();
if (!thr.IsAlive)
{
thr.Start();
}
button2.Enabled = true;
}
private void button2_Click(object sender, EventArgs e)
{
button2.Enabled = false;
mre.Reset();
button1.Enabled = true;
}
protected override void OnFormClosing(FormClosingEventArgs e) // if the program is closing, check the thread's state and act accordingly
{
mre.Set(); // make sure the loop continues so it can drop out
}
}

c# wanting multiple ui threads but getting cross-reference errors instead

i'm still very new at c#, threads and forms. i'm writing a small data acquistion program. it has two threads: the main ui thread and a sensor polling/logging/charting thread. when the user clicks the "start-logging" button, it it continuously polls the sensors (over a virtual COM port), writes the response to a file, updates the main form with some basic polling stats (how many pollings per second). if the user has clicked a "monitor" button, it opens a charting form and the polling thread invokes a methods that that adds the sensors values to the chart.
i have a version of this program that works very well but i found that if i have multiple charts open (so that i can view multiple sensors in realtime), the chart updates become sporadic or stop and only the window with the focus updates smoothly. (the comm port is only 56kbaud so it's not like the polling is being swamped with data.)
so i got the "bright" idea to make charting threads, thinking this would provide multiple UI loops and would produce nice smooth charting on multiple chart forms. below is simplified code; e.g. here, the charting thread is started with the polling thread instead of when the user clicks the "monitor" button. it compiles, but when it runs, i get a cross-reference error at the point when the update_chart method is called.
seems i have a fundamental misunderstanding of several things about threads and control ownership. the chart was made in the "charting" thread, but when the "polling" thread invokes the update_chart method, the code shows that update_chart methods is being run by the "main_ui" thread. i'm open to any suggestions/advise that'll give me smooth charting and stats updates. thanks.
namespace WindowsFormsApplication1
{
public partial class Main_Form : Form
{
delegate void UpdateUIStatsDelegate(string update);
UpdateUIStatsDelegate update_stats_delegate;
static BackgroundWorker polling_thread = new BackgroundWorker();
static BackgroundWorker charting_thread = new BackgroundWorker();
public static Chart_Form chart_form = new Chart_Form();
public Main_Form()
{
Thread.CurrentThread.Name = "main_ui";
update_stats_delegate = new UpdateUIStatsDelegate(update_stats);
polling_thread.DoWork += polling_thread_DoWork;
charting_thread.DoWork += charting_thread_start;
}
private void start_logging_Click(object sender, EventArgs e)
{
start_polling_thread();
start_charting_thread();
}
private void start_polling_thread()
{
polling_thread.RunWorkerAsync();
}
private void polling_thread_DoWork(object sender, DoWorkEventArgs e)
{
string sensor_values;
Thread.CurrentThread.Name = "polling";
while (true)
{
sensor_values = poll_the_sensors_and_collect_the_responses();
log_to_file(sensor_values);
// BeginInvoke(chart_form.update_chart_delegate, new object[] { sensor_values });
chart_form.BeginInvoke(chart_form.update_chart_delegate, new object[] { sensor_values });
pps = compute_polling_performance();
BeginInvoke(update_stats_delegate, new object[] { pps.ToString("00") });
}
}
private void update_stats(string stat)
{
string tn = Thread.CurrentThread.Name;
// this says "main_ui", but i don't get a cross-reference error
pollings_per_second.Text = stat;
}
private void start_charting_thread()
{
charting_thread.RunWorkerAsync();
}
private void charting_thread_start(object sender, DoWorkEventArgs e)
{
Thread.CurrentThread.Name = "charting";
Chart_Form chart_form = new Chart_Form();
chart_form.Show();
while (charting_is_active) { }
}
}
public partial class Chart_Form : Form
{
public delegate void UpdateChartDelegate(string sensor_values);
public UpdateChartDelegate update_chart_delegate;
public Chart_Form()
{
string tn = Thread.CurrentThread.Name;
update_chart_delegate = new UpdateChartDelegate(update_chart);
this.Text = "a realtime plot of sensor values";
}
private void update_chart(string sensor_values)
{
string tn = Thread.CurrentThread.Name;
// this says "main_ui" and i get a cross reference error; set below.
int x = extract_x_value(sensor_values);
int y = extract_y_value(sensor_values);
chart1.Series[X_AXIS].Points.AddY(x); // <<--- i get a cross-reference runtime error here...
chart1.Series[Y_AXIS].Points.AddY(y);
}
}
}

C# code fails to read serial input from Arduino

Hi I am trying to read serial input from my Arduino but I am having no luck. I believe I am opening and closing the connection correctly but do not appear to be having much success!
I'm sure the Arduino is outputting data because I can see it in the serial terminal.
The code for my C# program is below, I was wondering if anyone could spot any mistakes I may have missed.
Also this is an example of the serial data I should receive "12.2,1111,332,233"
namespace FridgeProtectionDeviceMonitor
{
public partial class Online_mode : Form
{
public Online_mode()
{
InitializeComponent();
}
private void Online_mode_Load(object sender, EventArgs e)
{
cmbPortSelection.DataSource = SerialPort.GetPortNames();
cmbChartSelection.SelectedIndex = 0;
}
string x = "";
SerialPort port;
private void btnFindPorts_Click(object sender, EventArgs e)
{
var ports = SerialPort.GetPortNames();
cmbPortSelection.DataSource = ports;
}
private void btnOpenPort_Click(object sender, EventArgs e)
{
if (cmbPortSelection.SelectedIndex > -1)
{
port = new SerialPort(cmbPortSelection.Text);
try
{
if (!port.IsOpen)
{
port.BaudRate = 9600;
port.Open();
}
}
catch (Exception)
{
MessageBox.Show("Serial connection request denied: Port is in use!");
}
}
else
{
MessageBox.Show("Serial connection request denied: No port selected!");
}
}
private void btnClosePort_Click(object sender, EventArgs ex)
{
try
{
port.Close();
}
catch (Exception)
{
MessageBox.Show("Serial close connection request denied: ", ex.ToString());
}
}
private void update(object sender, EventArgs e)
{
txtSaveLocation.Text = x;
}
private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
x = port.ReadLine().ToString();
MessageBox.Show(x);
this.Invoke(new EventHandler(update));
}
}
}
I was just working on the same thing as you, you'll have to modify it if you want to use it for your purposes, but here's the code I use that works. The only problem is that for me I need it to read very quickly because it's for a speedometer and it sort of lags (anyone know why?) but anyways here's my code that works for me.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void Form1_Load(object sender, EventArgs e)
{
try
{
if (arduinoCom.IsOpen == false)
{
arduinoCom.Open();
}
}
catch
{
MessageBox.Show("Serial Error: Is your serial plugged in?");
}
}
private void refresh_Tick(object sender, EventArgs e)
{
string speedReading = arduinoCom.ReadLine();
speed.Text = speedReading;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
arduinoCom.Close();
}
}
}
I've got a USB to serial converter linked to an XBee wireless bridge linked to PIC micro-controllers and i've found that running the serial port read functions in a separate thread increases communication speeds something chronic!
The readline blocks the code until the newline character is received, therefore blocking your main thread. Before i moved it to another thread my GUI became un-responsive etc.
By the way I'm using ReadByte().
I'm continuously reading bytes from the serial buffer in a backgroundworker and storing them in a thread safe queue. Then checking the queue for my communication start bits and analyzing the packet from there. Using manual reset events I'm syncing everything.
In my experience the port_datareceived event is a nice addition to the serialport class but unfortunately it is relatively useless for fast communications. I'm running at 12900 baud.
If you want code snippets i can provide them.
Regards,
Pete
P.S. I'm using an ATS5004D 4 channel differential oscilloscope with multichannel software. multichannel software can analyse the voltage signal into serial data through it's built in serial analyzer block. That way you can see what's actually being discussed on the serial comms lines!! cutting out all the BS other serial terminals add...
#michael b I'd start by looking at what the actual communication is doing i.e. scope the TX RX lines to see what the arduino board is putting out. I have only little experience with arduino but its predecessor the PICAXE system had a debug function which slowed everything down heaps, is something like this going on?
How many times per second do you want to update the speedo?
The SAE J1939 automotive serial communication standard says that RPM only needs to be updated once every 100ms. The human eye usually can't see/react faster than 300ms. 9600 baud gives you one 8bit byte per millisecond approx.
Personally I wouldn't use the timer to get the updates and instead do everything on a separate thread from main, and let it run as fast/slow as it wants.
this thread shows you roughly how i've set up my communications System.IO.IOException: A device attached to the system is not functioning C# .NET 4.0
hope it helps,
pete

Accessing UI from non-ui thread using dispatcher did not work

I am beginner to C# .net. I have simple app in wpf which access a listbox from user thread. in winforms i can use invokerequired, a equivalent for wpf using dispatcher did not help. My system also hangs for the buttons so debugging is though. Please provide solution for the below code. thanks in advance
private void Monitor_mtd()
{
while (AppStatus != 0)
{
if (flag2 == 1)
{
listBox1.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
new list1MtdDelegate(list1Mtd), "Best practice");
}
}
}
private delegate void list1MtdDelegate(string ls1);
private void list1Mtd(string ls1)
{
listBox1.Items.Add(ls1);
}
private void button1_Click_1(object sender, RoutedEventArgs e)
{
Monitor = new Thread(new ThreadStart(Monitor_mtd));
Monitor.Start();
flag1 = 1;
}
private void button2_Click(object sender, RoutedEventArgs e)
{
flag2 = 1;
}
There are a couple of issues that arise in your approach. Firstly, the way that you bind your data to the ListBox and secondly trying to update the ListBox from a user thread.
You can solve the binding of the ListBox by using an ObservableCollection so that the UI is updated with the necessary values (have a look at this post for more information on this). However, this also raises another problem and that is that the ObservableCollection cannot be called from another thread other than the one it is dispatching (see more on this here also). This means that you need another implementation for the ObservableCollection. Thomas Levesque made an AsyncObservableCollection that can be modified from any thread and still notify the UI when its modified.
I made a sample implementation that you can download here showing the full solution.

Gecko WebBrowser.ReadyState

I'm creating an application that contains "geckoWebBrowser" in c #. But I have to wait the complete loading a web page, and then continue to execute other instructions. there is something similar to WebBrowser.ReadyState? thank you very much
Hi GeckoWebBrowser has a DocumentCompleted event you could use it.
Edit:
for example you have a button to show url
private void ShowBtnClick(object sender, EventArgs e)
{
geckoWebBrowser1.Size = new Size(int.Parse(ViewportWidth.Text), int.Parse(ViewportHeight.Text));
geckoWebBrowser1.DocumentCompleted += LoadingFinished;
geckoWebBrowser1.Navigate(PageUrl.Text);
}
private void LoadingFinished(object sender, EventArgs args)
{
GeckoElement body = geckoWebBrowser1.Document.GetElementsByTagName("body")[0];
body.SetAttribute("style", "margin-top:-700px");
}
Try this :
private void WaitBrowser(Gecko.GeckoWebBrowser wb)
{
while (wb.IsBusy)
{
Application.DoEvents();
}
}

Resources