C
C#3y ago
Surihia

✅ Using a method that is running on another thread

I am making a program that does few operations to video files. on clicking a button, an dialog box is opened in which the user has to select the video file. Once the video gets selected in the dialog box, the operation will begin. here is where I encounter a problem. I want to write messages as each operation is done performing or when an operation is about to perform to a listbox in my GUI app. If this was a commandline app, I can just use Console.Writeline with my message strings but in a GUI app, I can't do something similar and so I decided to use the listbox command and here is where my issue begins. The issue is that all the messages will appear only when my program's whole video operation code is done performing and that defeats the whole point of using messages to tell the user that something is being performed when the operation is being done. I heard that I have to multi thread my app and so decided to put my whole video related code to another thread and then use a method to call the strings from my video extraction thread. I encounter a exception with this one stating that I can't access a method which is in another thread. Now the first message I write will be Parsing Video file.... and this message will appear once the video is selected in the dialog box and is being opened in a filestream. My code below should show as to how I am using a method to call the messages.
12 Replies
Surihia
SurihiaOP3y ago
Here is my code:
private void Msg(string text)
{
listBox1.Items.Add(text);
}


private void Ext_button1_Click(object sender, EventArgs e)
{
OpenFileDialog file_select = new OpenFileDialog();
file_select.Filter = "mkv files" + $"|*.mkv";
file_select.RestoreDirectory = true;


if (file_select.ShowDialog() == DialogResult.OK)
{

new Thread(t =>
{

Msg("Parsing video file...");
Msg("");

string VidMkv_file = file_select.FileName;

// rest of the code

}).Start();
private void Msg(string text)
{
listBox1.Items.Add(text);
}


private void Ext_button1_Click(object sender, EventArgs e)
{
OpenFileDialog file_select = new OpenFileDialog();
file_select.Filter = "mkv files" + $"|*.mkv";
file_select.RestoreDirectory = true;


if (file_select.ShowDialog() == DialogResult.OK)
{

new Thread(t =>
{

Msg("Parsing video file...");
Msg("");

string VidMkv_file = file_select.FileName;

// rest of the code

}).Start();
Kouhai
Kouhai3y ago
Assuming you're using WPF, you'd use Dispatcher.Invoke
Surihia
SurihiaOP3y ago
no not wpf. its winforms
Kouhai
Kouhai3y ago
You can useBeginInvoke
Kouhai
Kouhai3y ago
Surihia
SurihiaOP3y ago
can you tell me where exactly I have to put it in my code? I am worried if I end up causing a thread related issue like race condition in the process.
Kouhai
Kouhai3y ago
You'd replace your calls to Msg method with BeginInvoke, which should then call Msg In the example on MSFT's site
public delegate void MyDelegate(Label myControl, string myArg2);

private void Button_Click(object sender, EventArgs e)
{
object[] myArray = new object[2];

myArray[0] = new Label();
myArray[1] = "Enter a Value";
myTextBox.BeginInvoke(new MyDelegate(DelegateMethod), myArray);
}

public void DelegateMethod(Label myControl, string myCaption)
{
myControl.Location = new Point(16,16);
myControl.Size = new Size(80, 25);
myControl.Text = myCaption;
this.Controls.Add(myControl);
}
public delegate void MyDelegate(Label myControl, string myArg2);

private void Button_Click(object sender, EventArgs e)
{
object[] myArray = new object[2];

myArray[0] = new Label();
myArray[1] = "Enter a Value";
myTextBox.BeginInvoke(new MyDelegate(DelegateMethod), myArray);
}

public void DelegateMethod(Label myControl, string myCaption)
{
myControl.Location = new Point(16,16);
myControl.Size = new Size(80, 25);
myControl.Text = myCaption;
this.Controls.Add(myControl);
}
You can see BeingInvoke is called on the TextBox and the call back DelegateMethod is passed to it
Surihia
SurihiaOP3y ago
since I don't use a textbox is it like this then:
listBox1.BeginInvoke ("Parsing video file..."(Msg));
listBox1.BeginInvoke ("Parsing video file..."(Msg));
?
Kouhai
Kouhai3y ago
No, not quite like this, you need to pass the text in the second parameter like this
public delegate void MsgDelegate(sring text);
public delegate void MsgDelegate(sring text);
lixBox1.BeginInvoke(new MsgDelegate(Msg), "Parsing video file...");
lixBox1.BeginInvoke(new MsgDelegate(Msg), "Parsing video file...");
Or you can call it as an Action without declaring a delegate
lixBox1.BeginInvoke((Action)(() => Msg("Parsing video file..."));
lixBox1.BeginInvoke((Action)(() => Msg("Parsing video file..."));
Surihia
SurihiaOP3y ago
is there a way to ensure that the Button on my app is not interactable until the operation is completed ?
Kouhai
Kouhai3y ago
Set Enabled to false
Accord
Accord2y ago
Closed!
Want results from more Discord servers?
Add your server