Thread.Sleep() doesn't work with Cv2.ImShow, OpenCvSharp, C# - c#

Very Simple C# Winforms App, OpenCVSharp4, Thread.Sleep() doesn't work.
It seems like (as I guess) Cv2 cannot be used in multiple threads, eg, one thread create NamedWindow, another thread ImShow. But this simple code below is still confusing.
private void button1_Click(object sender, EventArgs e)
{
VideoCapture video = new VideoCapture("E:/RankingBack.mp4");
Mat frame = new Mat();
while (true)
{
video.Read(frame);
Cv2.ImShow(" ", frame);
//Cv2.WaitKey(33); // WORKS
Thread.Sleep(33); // DOES NOT WORK
}
frame.Dispose();
video.Release();
Cv2.DestroyAllWindows();
}

waitKey's purpose is not waiting, it's to spin the GUI event loop that OpenCV uses. If you don't call it, OpenCV's GUI doesn't work.
You're using C# and WinForms already (judging by the tags), so you should use WinForms instead of imshow. OpenCV does its own GUI event handling, which may conflict with other GUI toolkits that are being used in the same program.
OpenCV's GUI functions are generally not safe to call from threads because some GUI backends don't allow that. That's irrelevant though because...
You do not have a "thread" here. You have the handler for a button click event. That's executed by the event loop of your WinForms application. That happens in the main thread that is always there in every process. That is not a spawned thread.

Related

Enable button clicking while another process is running

I look trough google a bit but cant make it work.
I have some process done when i push a button.
I want to add a "Kill All" button to terrminate everying when pushed, but when i start a process i cant push any other button untill its finnished.
private void button_checkZero_phones_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(WorkThreadFunction));
thread.Start();
}
private void button_kill_all_Click(object sender, EventArgs e)
{
System.Environment.Exit(1);
}
You have to run your "Kill All" method in an async method. The main thread is always blocked when you run a long process.
More info about your problem:
WinForm Application UI Hangs during Long-Running Operation
Just use one of the following methods - run Kill All in:
A BackgroundWorker
Another thread
Another task
Use async/await
Reactive extensions
There are a several ways to notify you that the all processes are terminated! It depends on which method you use.
Use async funcations. I found these useful links
http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx
http://msdn.microsoft.com/en-us/library/vstudio/hh156513.aspx
Is this a Windows app? If you're feeling old-school and enjoy winding up other developers, stick an Application.DoEvents() in your loop of death.
You know you want to.
Of if you want to do it without receiving scorn from all your peers, see this question and answer.

how to create thread work with gui

I'm novice in program with c#. I want to create thread that move label in the main UI without stuck the UI until the movement done
I built something but it didnt work
tell me what is my problem
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(Movelb);
t.IsBackground = true;
t.Start();enter code here
}
private void DOsomeThing()
{
label2.Visible = true;
label2.Location = new Point(0, 205);
for (int i = 0; i < 533; i++)
{
label2.Location = new Point(i, 205);
Thread.Sleep(10);
}
label1.Text="false";
}
private void Movelb()
{
if (this.InvokeRequired)
{
threadDel d = new threadDel(DOsomeThing);
this.BeginInvoke(d);
}
else
DOsomeThing();
}
Do not use threads to paint to forms or modify/update form contents. The recommended paradigm in Windows programming is One Thread Per Form or Window. If you want to create forms that run from separate threads, then you must
create the new thread first
create the Form on the new thread
In this way, the new thread will serve as the new Form's message handler. But even then, you should still do all manipulation of the Form within that thread (and if the form wants to modify contents in another form running on a different thread, then some additional thread-safe communication trickery may be required).
To animate window contents, you should use System.Windows.Forms.Timer instead, which executes on the Form's thread in lock-step with its other messages. You'll need to re-implement your animation as a state machine rather than a for() loop construct, though. That means the variables for Label position will need to be embedded into the Form class, so that updates can be preserved across Timer message invocations.
You need to understand the event model first. In event-driven environments like Windows or Android or Linux etc... the "automatic " tasks such as animations of coordinates or other properties are usually done using Timers that keep re-sending events back to the handler that advances the animation/process. In your particular example - if you need to move label, use Widows.Forms.Timer. It is not appropriate to block UI thread that processes events with lengthy tasks as UI thread will stall and your app will freeze or become jerky. NOW, on the other hand there are many cases when adding extra threads DOES help a lot, when? Not in your case, because you only change the coordinate of the label that is nothing in terms of CPU in comparison to repaint, so your solution with extra thread is LESS efficient and much more complex than using timer. An extra thread is beneficial only when the logical work it performs on animation model is comparable or out-weights the paint work- imagine a game where 200 bugs need to be animated on screen according to many logical rules, in this case bug painting may be done in UI thread, but bug property changes/animations may be done in another thread if those computations are intense.
How Events work?
An OS has an infinite loop inside that gets interrupted by keyboard, mouse and other events but the loop spins indefinitely until you shut down Windows (or Android or XWidnws...). At the end of the loop the OS looks at "raw" mouse/key events and dispatches them into appropriate application queue. It knows it by inspecting every app windows list, who is on top and thus it knows what window/app was under such and such X,Y mouse coordinate. When event gets dispatched to your app your job is to handle it very fast and look for another event in your queue (queues are bound to UI Threads/Windows).
How Timers Work?
A timer is a special kind of event that OS can keep sending to you periodically from its internal "infinite loop". OS keeps track of what apps requested to be notified and how often - when time comes, it adds a WM_TIMER(on MS Windows) into your windows queue. This way you don't block anything, but get a method in your code that gets called every X milliseconds. When you use .NET Timer class - it is just a wrapper around CreateTimer() KillTimer() (I dont recall exact func names) in Windows User APIs. .NET Timer also knows how to swallow the WM_TIMER and call a C# event/delegate for you.
I hope this helps!
Your code does nothing useful. It just starts a new background thread, which, in turn, invokes a delegate, being executed at the same UI thread, which had started... the background thread.
In other words, you can't move the label in worker thread, because moving the label brings to repainting, which can't be done from background thread.
I also had an idea of doing some work in a thread - and while this hard job
was carried out... the main-gui-form should be modified, so the user will
spot a progress.
Did some lookup and went into "delegates", "eventhandlers", and "very advanced pieces of code".
It took me some time to fix, and I came up with this very simple example. Have a look.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ProcessingUI
// You will find a form with "button1": will do some work in a seperate thread, and
// therefore you are allowed to do action in main-gui-form while this work is done,
// due to async. operation.
// While work is done in seperate thread - the main-gui-form will have a label modified...
// having the steps: 1,2,3,0.
// Also found... "button2": will do some work in same thread as gui, and
// therefore you are not allowed to do action in main-gui-form while this work is done,
// due to sync. operation (only one thread is established).
// While work is done in one-and-only-thread - the main-gui-form will have a label modified...
// having the steps: 1,2,3,0.
{
public delegate void UpdateTextDelegate();
public partial class Form1 : Form
{
public delegate void SetStatusText(string statusText);
public SetStatusText mySetStatusTextDelegate;
public Form1()
{
InitializeComponent();
mySetStatusTextDelegate = new SetStatusText(SetStatusTextMethod);
}
private void button1_Click(object sender, EventArgs e) // do work from new thread.
{
Worker w = new Worker(this);
Thread thread1 = new Thread(new ThreadStart(w.DoWork));
thread1.Start();
}
private void button2_Click(object sender, EventArgs e) // do work from local class - form is locked during 1-3 steps.
{
SetStatusTextMethod("1");
Thread.Sleep(3000);
SetStatusTextMethod("2");
Thread.Sleep(3000);
SetStatusTextMethod("3");
Thread.Sleep(3000);
SetStatusTextMethod("0");
}
public void SetStatusTextMethod(string statusText)
{
label1.Text = statusText;
label1.Refresh();
}
}
public class Worker
{
Form1 guiForm; // holds form where "control-to-be-changes" is found.
public Worker(Form1 _guiForm)
{
guiForm = _guiForm;
}
public void DoWork() // while steps are being done - form can easily be moved around... is not locked!
{
// put "1/3" on form.
guiForm.Invoke(guiForm.mySetStatusTextDelegate, "1");
Thread.Sleep(3000);
// put "2/3" on form.
guiForm.Invoke(guiForm.mySetStatusTextDelegate, "2");
Thread.Sleep(3000);
// put "3/3" on form.
guiForm.Invoke(guiForm.mySetStatusTextDelegate, "3");
Thread.Sleep(3000);
guiForm.Invoke(guiForm.mySetStatusTextDelegate, "0");
}
}
}

Need explanation on event handling and delegates

I have some code that I wrote, which does what I want. However, I am not quite sure how, exactly, it works. The part I am having the most trouble with is the last part. I had a textBox1.Text = "test" which did not work. I got a run time error about it being called from a different thread. When I put the textBox1.Invoke(etc etc), it worked as expected. Why?
As you can see, I know just enough to be dangerous and I really want to understand what's going on here instead of blindly copying and pasting from sites around the web.
I have the following in a class named SerialCommunicator:
public SerialCommunicator(SerialPort sp)
{
this.sp = sp;
sp.ReceivedBytesThreshold = packetSize;
sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
sp.Open();
}
public void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(50);
SerialPort s = (SerialPort)sender;
byte[] buffer = new byte[128];
s.Read(buffer, 0, s.BytesToRead);
}
Then, in my Form1.cs I have a button that when pressed does the following:
private void btnPortOK_Click(object sender, EventArgs e)
{
string comPort = cboComPorts.SelectedItem.ToString();
SerialPort sp = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One);
sp.DataReceived += new SerialDataReceivedEventHandler(DataHasBeenReceived);
comm = new SerialCommunicator(sp);
}
public void DataHasBeenReceived(object sender, EventArgs args)
{
textBox1.Invoke(new EventHandler(delegate { textBox1.Text += "test"; }));
}
This is thread-affinity. UI controls don't like to be touched by anything except the thread that created them, but the DataReceived thread happens from a different thread. Adding a call toControl.Invoke pushes an item of work back to the UI thread, so the Text updated can succeed.
I am not an expert on this (there will likely be better answers than this). But as I understand it, the GUI thread "owns" your form. So when you try to update it from a different thread you are crossing the streams.
The Invoke is a way to ask the GUI thread to run a method. Method that it runs is your textBox1.Text += "test";
The idea is by invoking a delegate, that will ask the GUI thread to make the change, rather than just changing the value yourself. This allows allow the change to be done in a thread safe manner.
Here is a good article by Jon Skeet on this issue:
http://www.yoda.arachsys.com/csharp/threads/winforms.shtml
Events are called from the thread where they happen. (Unless specified otherwise).
Think about this way:
When you activate the event, it is actually called as a finction EventName(). So calling an event means actually going to all the methods that were registered to that event and doing them.
But, this is done in the same thread in a serial way.
So if an event happened in a thread that is not your UI thread you'll get theat error.
The issue is that the GUI components only accepts modifications from the GUI thread. So when other threads want to modify the GUI, then they must queue their modification code using measures like control.Invoke(...) which will queue the delegate to be processed as soon as possible on the GUI event queue, and thus the correct thread.
What you run in to is that one of the built-in checks are fired than controls that the calling thread indeed is the correct thread. It is a security measure that makes debugging easier (if they were not present you would have to debug subtle threading issues instead...)
textBox1.Text = "test" doesn't work because you are calling it from another thread (i.e. the DataHasBeenReceived event) then the thread who owns the textbox. That's usually the thread in which your application runs and that creates your GUI interface (and thus your textbox). Invoke works because that methods switches to the GUI thread, sets your text and then switches back to the thread of your DataHasBeenReceived event.
In Net 1.0 and 1.1 you could use GUI controls from another thread then then the one that owned them but this resulted in a lot of problems when threads started accessing the controls at the same time. So, since net 2.0 Microsoft changed that.
If you want to know if must use invoke or not (i.e. if a method can be called from the both the GUI thread or another thread), you can use the property InvokeRequired combined with an if else. A invoke call is slightly more expensive then a direct manipulation of the control.

c# calling backgroundWorker from another thread than UI thread

I'm trying to load loadingForm like below code. But it doesn't work, the loadingForm doesn't disappear, the event RunWorkerCompleted doesn't get called.
And also, I need to call loadingForm and backgroundWorker multiple times, so how do I completely dispose the loadingForm and the backgroundWorker after each call?
I think that there're many things wrong in my code but I don't know how to fix it. Could you show me how to solve my problem and point out where I need to fix? Thanks a lot in advance.
public partial class loginForm : Form
{
//....
private loadingForm lf;
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
lf.Show();
While (backgroundWorker1.isBusy)
Application.DoEvents();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, DoWorkEventArgs e)
{
lf.Close();
}
private void connect()
{
//....
Thread mainThread = new Thread(ThreadStart(listentoServer));
mainThread.Start();
}
private void listentoServer()
{
//....
lf = new loadingForm();
backgroundWorker1.RunWorkerAsync();
//....
backgroundWorker1.CancelAsync();
//....
}
}
There's a lot of things wrong with your code. If you can, try to take a step back and describe what exactly you want to do.
BackgroundWorker uses the Event-based Asynchronous Pattern (EAP). As such, it requires a thread context in which to live. UI threads satisfy this requirement, but manually-created Thread instances do not (unless you install one or make the instance a secondary UI thread).
Similarly, UI components bind to a particular thread. They require an STA thread that does message pumping (e.g., Application.DoEvents).
It looks to me like you're creating a manual Thread and then creating UI components from that thread (so you know that the thread should be STA and include a message pumping loop, neither of which are in your code). Then that thread starts a BGW which does message pumping.
It's not clear what you're trying to accomplish here - maybe displaying a dialog in a separate thread?
Multiple UI threads in a WinForms app is not an officially supported scenario AFAIK, though some people have gotten it working. I've never seen a need for it, though.
According to what you have shown (which is admittedly incomplete, so this may not be the problem), you are not hooking up your event to the backgroundWorker_DoWork and backgroundWorker_RunWorkerCompleted event handlers. Somewhere (after you instantiate your backgroundWorker), you should have this:
backgroundWorker.DoWork += new EventHandler(backgroundWorker_DoWork);
backgroundWorker.RunWorkerCompleted += new EventHandler(backgroundWorker_RunWorkerCompleted);
As a disclaimer, this was written by hand, so the event names or EventHandler types may be incorrect.
i really don't know how to fix your code definitively, or if your code even works the way you have it, i can only give you the following guidance.
use CancellationPending property of background worker, not the IsBusy property
when working with windows forms and threaded code, always use the Invoke/BeginInvoke methods to make sure you marshal your call back to the thread that the control originated from.

C# - Can Threads behave like BackgroundWorkers (winForms)?

I'm trying to work with Threadding and it seems to me like it's suspiciously difficult (I'm probably doing it wrong).
I want to load a file inside a BackgroundWorker and while that happens, "send" each new line to a separate Thread (not bgWorker). I'm using BlockingCollection and Add() each line, then I want to Take() them and process them in another thread.
Now, everything is straightforward with the BgWorker; but why is it impossible(isn't it?) to just declare a new thread in Form1.cs and have it perform like the BgWorker? In other words, why must you create a separate WorkerClass ( http://msdn.microsoft.com/en-us/library/7a2f3ay4(VS.80).aspx )?
I'm asking this because, you can access your BlockingCollection fine from within the BackgroundWorker, but you can't do it from a separate WorkerClass (since it's a plain vanilla separate class). (So what's the point of the BlockingCollection then if you can't use it for what it's meant?)
Also, BgWorkers have a ReportProgress(...) event/method. As far as I know, if you use that msdn example, you don't have squat in your Thread.
What am I missing here? Please help.
PS: Before you jump and tell me that It's not in any way more efficient to send lines to another thread, know that I'm doing this as a learning exercise. Trying to figure out how Threads work in C# and how you sync/communicate between/with them (and/or bgWorkers).
Answering specifically why working with threads is more difficult than working with a background worker....
The backgroundworker is actually a method for creating another thread wrapped up in an easier to use package. The reason working with threads directly is harder is because it's closer to the real thing.
For a similar comparison, using System.Net.Mail to send an email is just a simplified way of creating socket connections, etc... Under the hood, the System.Net.Mail classes do the detailed work. Similarly, under the hood, the BackgroundWorker does the detailed work of dealing with the threads.
As a matter of fact, the MSDN documentaiton for the backgroundWorker object starts out like this:
BackgroundWorker Class Updated:
September 2010
Executes an operation on a separate
thread.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
So if the backgroundworker class is supposed to make threading easier, why would people want to work with threads directly? Because of the issue you're having. Sometimes the "friendly wrapper" leads to a loss of fine control.
Edit - added
What you're asking about in the comments is thread synchronization. This article covers it pretty well.
http://msdn.microsoft.com/en-us/magazine/cc164037.aspx
and this article answers "communicating between threads" explicitly.
http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic63233.aspx
To answer your question in the title, yes "normal" threads can act like BackgroundWorker threads. You just have to create more of the wiring code yourself.
I wrote a simple application for scanning my music collection using a manually created thread. The main body of the thread is a method that loops over all of the folders under a specified root and fires an event each time it encounters a folder that contains some mp3 files.
I subscribe to this event in the main form of my application and update a DataGridView with the new information.
So the thread is kicked off by the following code:
this.libraryThread = new Thread(new ThreadStart(this.library.Build)) { IsBackground = true };
// Disable all the buttons except for Stop which is enabled
this.EnableButtons(false);
// Find all the albums
this.libraryThread.Start();
The method supplied to ThreadStart does some housekeeping and then calls the method that does the work:
private void FindAlbums(string root)
{
// Find all the albums
string[] folders = Directory.GetDirectories(root);
foreach (string folder in folders)
{
if (this.Stop)
{
break;
}
string[] files = Directory.GetFiles(folder, "*.mp3");
if (files.Length > 0)
{
// Add to library - use first file as being representative of the whole album
var info = new AlbumInfo(files[0]);
this.musicLibrary.Add(info);
if (this.Library_AlbumAdded != null)
{
this.Library_AlbumAdded(this, new AlbumInfoEventArgs(info));
}
}
this.FindAlbums(folder);
}
}
When this method finishes a final LibraryFinished event is fired.
I subscribe to these events in the main form:
this.library.Library_AlbumAdded += this.Library_AlbumAdded;
this.library.Library_Finished += this.Library_Finished;
and in these methods add the new album to the grid:
private void Library_AlbumAdded(object sender, AlbumInfoEventArgs e)
{
this.dataGridView.InvokeIfRequired(() => this.AddToGrid(e.AlbumInfo));
}
and finish off (which reenables buttons etc.):
private void Library_Finished(object sender, EventArgs e)
{
this.dataGridView.InvokeIfRequired(() => this.FinalUpdate());
}
As you can see this is a lot of work which would be a whole lot simpler if I used a BackgroundWorker.

Categories