A blocking call in the GUI thread also blocks the visualisation of HALCON: Instead of seeing the desired result, a black HALCON window is displayed.
To overcome this problem, we will separate the GUI and other tasks in multiple threads, so that they run individually and asynchronously. Have a look at the following code, which is taken from a standard example Multithreading (%HALCONEXAMPLE%c#Multithreading).
public Thread threadAcq, threadIP;
FuncDelegate delegateDisplay;
threadAcq = new Thread(new ThreadStart(ImgAcqRun)); threadIP = new Thread(new ThreadStart(IPRun)); delegateDisplay = new FuncDelegate(DisplayResults);
public void DisplayResults()
{
hWindow.DispObj(hImage);
}
public void ImgAcqRun()
{
while (true)
{
HImage grabbedImage = hFramegrabber.GrabImageAsync(-1); newImgEvent.Set();
}
}
public void IPRun()
{
while (newImgEvent.WaitOne())
{
mainForm.Invoke(delegateDisplay);
}
}
In this example, there are three threads running in parallel: The main thread is in charge of the GUI and starts other threads, threadAcq is responsible for image acquisition, and threadIP for image processing. This is a typical asynchronous programming design. The threadAcq thread starts to grab an image, saves it in a queue and sends a signal to thread threadIP. threadIP waits for the signal, and calls DispObj() to display the image. The GUI thread, which is not blocked by any endless loop, could update the window and display the image immediately.
Similar like this asynchronous programming style, we can open a new thread to solve the black screen in visualize_object_model_3d. Please look at the following example.
HDevProcedure Procedure;
HDevProcedureCall ProcCall;
Thread threadIP = new Thread(new ThreadStart(IPRun));
private void runBtn_Click(object sender, EventArgs e)
{
threadIP.Start();
}
public void IPRun()
{
Procedure = new HDevProcedure(“visualize_object_model_3d”);
ProcCall = new HDevProcedureCall(Procedure);
ProcCall.SetInputCtrlParamTuple(“WindowHandle”, hWindow);
ProcCall.SetInputCtrlParamTuple(“ObjectModel3D”, hObjectModel);
ProcCall.Execute();
}
Here we open a new thread to call this procedure via HDevEngine, which includes an endless loop. Since the procedure runs in a worker thread, the GUI will not be influenced.
There are many other methods for asynchronous programming, e.g., using System.Threading.Tasks from .NET. Some of them might be more intuitive and require less coding. Deciding which of them to use strongly depends on your programming experience and your application’s requirements. Generally speaking, visualisation is not easy if you want to develop your own vision application based on a programming language, since it requires special programming knowledge, e.g., in architecture design, thread design, and so on.