How to run a void function in the background - visual-c++

I have created a windows form application (CLR Project). When i click the start button, a void function with while loop runs. But the problem is the windows form becomes non-responsive (Not Responding). What I want to do is I want to run the function in the background when the button is clicked and make it stop with a click too and be able to use the windows form. Please help.
My code looks like this:
bool isStarting = false;
btnStart_Click(System::Object^ sender, System::EventArgs^ e){
if(isStarting){
isStarting = false;
}else{
isStarting = true;
runCode(param1, param2, param3);
}
}
void runCode(param1, param2, param3){
while(isStarting){
//do something
}
}

Not Responding occurs when program fall into infinite loop.
In your program, you used infinite loop in runCode method.
This will be fixed when you use thread for infinite loop or else.
So I suggest you to use thread.

Related

IrrKlang Sound Library and Stop Event threads

I have a question about using external c++ library (irrKlang.dll) which is an audio playback engine. Now, the problem is that when I get a SoundStopped event out of it, and do an action in the main form, all kinds of stack related errors arise. Let me show the code:
namespace WindowsFormsApplication4
{
public class IsoundFinished : ISoundStopEventReceiver
{
public delegate void OnSoundStoppedEventHandler(object source, EventArgs e);
public event OnSoundStoppedEventHandler IStopped;
public void OnSoundStopped(ISound iSound, StopEventCause reason, object userData)
{
if (reason.ToString() == "SoundFinishedPlaying")
IStopped?.Invoke(this, EventArgs.Empty);
}
}
}
That is an extended class for me to do custom actions (for example - if sound finished, raise the event...) I am creating an instance of it, for the event action to get exposed in my main Form1 class:
IsoundFinished iStopReceiver = new IsoundFinished();
Now in my main form, I have this line in my Form1() method, just under my InitializeComponent():
iStopReceiver.IStopped += new soundFinished.OnSoundStoppedEventHandler(OnStopped);
It's for subscribing to the event handler. And finally - my OnStopped() method which is supposed to do stuff when the song ends it's playback - it's on the same Form1:
private void OnStopped(object sender, EventArgs e)
{
if (InvokeRequired)
{
Invoke(new Action<object, EventArgs>(OnStopped), sender, e);
return;
}
btnStop1.PerformClick();
}
My Stop1 button method is (for those who work with the IrrKlang) ISound.Stop(); and few more lines of code, dealing with the display of playlist and so on. Although I have invoked it from the main UI thread - which should provide me with some degree of thread misalignment protection, all kinds of errors appear, mostly
Cannot evaluate expression because a native frame is on the top of the call stack.
Of course, if I do it without event handler, ISound.Stop(); drops the sound from the engine, like it should. I know something wrong is happening with the threads, but I can't figure out what's going on. If someone would give me few tips, I'd appreciate that a lot.
Well it seems I've solved it myself ! It's all about understanding how the threads are working in Visual C#. The problem was this : I was actually PAUSING the background thread where my audioengine was triggering the event - so 'till I performed an action after INVOKE in the main UI thread, background thread was paused along with the whole irrKlang engine. It was unable to purge itself properly, so it's call stack got clogged!
Using BEGININVOKE solved the problem, as it doesn't PAUSE the background task. It lets it run instead. Diagram on this answer gave me much needed piece of info I was looking for.
Maybe someone will need this answer too, glad I helped myself :P
private void OnStopped(object sender, EventArgs e)
{
if (InvokeRequired)
{
BeginInvoke(new Action<object, EventArgs>(OnStopped), sender, e);
return;
}
btnStop1.PerformClick();
}

how to use a separate STA thread to call clipboard from timer in console application?

I am struggling with using Clipboard from a console application. The error handler would return the following error.
"Current thread must be set to single thread apartment (STA) mode before OLE calls can be made"
I set the STA attribute to the main function and that worked well when calling from main. However, I need to cyclically call that function and in this case I get back that error.
I'm trying to figure out how to use an own thread in my funtion. Now, it just works once but in the 2nd call from my timer, I am not able to reach the area of the code after where I created the thread
public string getRawData()
{
string sChatRawTxt = string.Empty;
try
{
// copy data to clipboard using an Autoit script
Process.Start("copyChatToClipboard.au3");
System.Threading.Thread.Sleep(500);
Thread staThread = new Thread(x =>
{
if (Clipboard.ContainsText())
{
sChatRawTxt = Clipboard.GetText();
Clipboard.Clear();
}
});
staThread.SetApartmentState(ApartmentState.STA);
staThread.Start();
staThread.Join();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return sChatRawTxt;
}
This is the timer from where my function is called. If I set a breakpoint to separateComments, it only works one time, then I am no longer able to reach that position. Do I have to somehow close the thread from before?
public void OnTimedEvent_scannerCyclic(object source, ElapsedEventArgs e)
{
string sRawTxt = getRawData();
// then separate/ remove the useless data
string sComments = SeparateComments(sRawTxt);
}
[STAThread]
public static void Main(string[] args)
{
stdTimer = new System.Timers.Timer(1000);
stdTimer.Elapsed += new ElapsedEventHandler(this.OnTimedEvent_scannerCyclic);
stdTimer.Enabled = true;
while (true)
{
// main program
//System.Threading.Thread.Sleep(1000);
}
}
thanks a lot for help
So the only solution i figured was to use my own timer that i implemented in the main as below
TimeSpan deltaT = TimeSpan.FromMilliseconds(1000);
DateTime timeLastCall = DateTime.Now;
while (true)
{
// main program
DateTime currentTime = DateTime.Now;
if(currentTime - timeLastCall > deltaT)
{
Scanner.mainCyclicCall();
timeLastCall = currentTime;
}
System.Threading.Thread.Sleep(100);
}
I dont have a lot of c# experience, it is actually my first little project. I dont know if there is a better way to cyclically access Clipboard in a console application. Also using a dispatcher timer did not work out, I read console apps dont have a dispather.

Multithreading in UI

I have a winform from where the user starts a process with a button click and I display the running process information on another winform running on different thread. The code in the button click is as below:
private void btn_Click(object sender, EventArgs e)
{
Thread th=new Thread(ShowInfoForm);
th.Start();
//Code for process execution
EditInfoForm();
th.Join();
this.BringToFront();
}
private void ShowInfoForm()
{
infoForm = new InfoForm();
infoForm.showBox("Process Started", infoForm.MsgLevel.INFO,ButtonOK.DISABLED);
}
private void EditInfoForm()
{
infoForm.Invoke((MethodInvoker)(() => infoForm.EditBox("Process Completed", infoForm.MsgLevel.INFO,ButtonOK.ENABLED));
}
Everything works fine except the bringToFront call on the main thread. After exiting the info form on its "OK" button click, the main form goes back in the z order. How can I resolve this?
P.S. I understand that the best practice is to keep UI in the same thread and run processes on background threads, but this is a huge bulk of code and I cannot edit it.

A threading problem where mono hangs and MS.Net doesn't

I'm testing my app with mono in prevision of a Linux port, and I have a threading problem. I initially considered pasting 3000 code lines here, but finally I've devised a small minimal example ;)
You have a form with a button (poetically named Button1, and a label (which bears, without surprise, the name Label1)). The whole lot is living a happy life on a form called Form1. Clicking Button1 launches an infinite loop that increments a local counter and updates Label1 (using Invoke) to reflect its value.
Now in Mono, if you resize the form, the label stops updating, never to restart. This doesn't happen with MS implementation. BeginInvoke doesn't work any better; worse, it makes the UI hang in both cases.
Do you know where this discrepancy comes from? How would you solve it? And finally, why doesn't BeginInvoke work here? I must be making a huge mistake... but which?
EDIT:
Some progress so far:
Calling BeginInvoke does in fact work; only, the UI just doesn't refresh fast enough, so it seems to stop.
On mono, what happens is that the whole thread hangs when you insert a message in the UI queue (eg by resizing the form). In fact, the synchronous Invoke call never returns. I'm trying to understand why.
Of interest: even using BeginInvoke, the asynchronous calls don't get executed before the resizing operation ends. On MS.Net, they keep running while resizing.
The code looks like this (C# version lower):
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim T As New Threading.Thread(AddressOf Increment)
T.Start()
End Sub
Sub UpdateLabel(ByVal Text As String)
Label1.Text = Text
End Sub
Delegate Sub UpdateLabelHandler(ByVal Text As String)
Sub Increment()
Dim i As Long = 0
Dim UpdateLabelDelegate As New UpdateLabelHandler(AddressOf UpdateLabel)
Try
While True
i = (i + 1) Mod (Long.MaxValue - 1)
Me.Invoke(UpdateLabelDelegate, New Object() {i.ToString})
End While
Catch Ex As ObjectDisposedException
End Try
End Sub
End Class
Or, in C#,
public class Form1
{
private void Button1_Click(System.Object sender, System.EventArgs e)
{
System.Threading.Thread T = new System.Threading.Thread(Increment);
T.Start();
}
public void UpdateLabel(string Text)
{
Label1.Text = Text;
}
public delegate void UpdateLabelHandler(string Text);
public void Increment()
{
long i = 0;
UpdateLabelHandler UpdateLabelDelegate = new UpdateLabelHandler(UpdateLabel);
try {
while (true) {
i = (i + 1) % (long.MaxValue - 1);
this.Invoke(UpdateLabelDelegate, new object[] { i.ToString() });
}
} catch (ObjectDisposedException Ex) {
}
}
}
This is a bug in the mono runtime, at least I think it is. The code might not be good practice (I'm not a threading expert), but the thing that suggests a bug is the fact that the behaviour differs on windows and Linux.
On Linux, mono has exactly the same behaviour as MS.Net has on windows. No hanging, continuous updates even while resizing.
On Windows, mono displays all the aforementioned problems. I've posted a bug report at https://bugzilla.novell.com/show_bug.cgi?id=690400 .
Do you know where this discrepancy
comes from? How would you solve it?
I am not sure. I do not see anything obvious in your code that would cause the difference between Mono and .NET. If I had to make a wild guess I would say there is a possibility that you have stumbled upon an obscure bug in Mono. Though, I suppose it is possible that Mono uses a sufficiently different mechanism for handling the WM_PAINT messages that cause the form to get refreshed. The constant pounding of the UI thread from repeated calls to Invoke may be disrupting Mono's ability to get the form refreshed.
And finally, why doesn't BeginInvoke
work here?
Calling Invoke in a tight loop is bad enough, but BeginInvoke will be even worse. The worker thread is flooding the UI message pump. BeginInvoke does not wait until the UI thread has finished executing the delegate. It just posts the requests and returns quickly. That is why it appears to hang. The messages that BeginInvoke is posting to the UI message queue keep building up as the worker thread is likely severely out pacing the UI thread's ability to process them.
Other Comments
I should also mention that the worker thread is nearly useless in the code. The reason is because you have a call to Invoke on every iteration. Invoke blocks until the UI has finished executing the delegate. That means your worker thread and UI thread are essentially in lock-step with each other. In other words, the worker is spending most of its time waiting for the UI and vice versa.
Solution
One possible fix is to slow down the rate at which Invoke is called. Instead of calling it on every loop iteration try doing it every 1000 iterations or the like.
Any even better approach is to not use Invoke or BeginInvoke at all. Personally, I think these mechanisms for updating the UI are way overused. It is almost always better to let the UI thread throttle its own update rate especially when the worker thread is doing continuous processing. This means you will need to place a timer on the form and have it tick at the desired refresh rate. From the Tick event you will probe a shared data structure that the worker thread is updating and use that information to update the controls on the form. This has several advantages.
It breaks the tight coupling between the UI and worker threads that Control.Invoke imposes.
It puts the responsibility of updating the UI thread on the UI thread where it should belong anyway.
The UI thread gets to dictate when and how often the update should take place.
There is no risk of the UI message pump being overrun as would be the case with the marshaling techniques initiated by the worker thread.
The worker thread does not have to wait for an acknowledgement that the update was performed before proceeding with its next steps (ie. you get more throughput on both the UI and worker threads).
First and foremost: clicking on Button1 is asynchronous already, so you don't need to create another thread to increment, just call the increment method Sorry, I was reading your question line by line and by the time I got to the while-loop I forgot about the button:
private void Button1_Click(System.Object sender, System.EventArgs e)
{
Thread t = new Thread(Increment);
t.IsBackground = true;
t.Start();
}
Second: if you do need to use a thread then you should always set your thread to background (i.e. foreground prevents your process from terminating), unless you have a good reason for using a foreground thread.
Third: if you're making updates to the UI, then you should check the InvokeRequired property and call BeginInvoke:
public void UpdateLabel(string Text)
{
if (InvokeRequired)
{
BeginInvoke(new UpdateLabelDelegate(UpdateLabel), Text);
}
else
{
Label1.Text = Text;
}
}
public void Increment()
{
int i = 0;
while(true)
{
i++; // just incrementing i??
UpdateLabel(i.ToString());
Thread.Sleep(1000);// slow down a bit so you can see the updates
}
}
You can also "automate" the Invoke Required "pattern": Automating the InvokeRequired code pattern
And now see if you're still having the same problem.
I tried it on my machine and it works like a charm:
public partial class Form1 : Form
{
private delegate void UpdateLabelDelegate(string text);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(Increment);
t.IsBackground = true;
t.Start();
}
private void UpdateLabel(string text)
{
if (label1.InvokeRequired)
{
BeginInvoke(new UpdateLabelDelegate(UpdateLabel), text);
}
else
{
label1.Text = text;
}
}
private void Increment()
{
int i = 0;
while (true)
{
i++;
UpdateLabel(i.ToString());
Thread.Sleep(1000);
}
}
}

Multiple instances of j2me midlet problem

I have a j2me midlet running on a cell phone. The code works fine, but the issue that comes up is that the program seems to be running more than one instance of itself. I have code at the beginning of the application inside the appStart() method that runs twice when the application starts. During the lifetime of the program, the code can be seen running twice when text is written to the screen.
The code looks like this:
public MyClass()
{
form = new Form("MyProgram");
cmdClose = new Command("EXIT", Command.EXIT, 1);
form.addCommand(cmdClose);
form.setCommandListener(this);
display = Display.getDisplay(this);
display.setCurrent(form);
}
public void startApp()
{
form.append("App starting\n");
// Rest of program
}
I have no idea why the code is being called twice.
I'm coding on the i290.
This is definitely a JVM bug. startApp() should be called only once at startup and can't be called again until pauseApp() is called or you call notifyPaused() yourself.
What I suggest is the following code:
private boolean midletStarted = false;
public void startApp() {
if (!midletStarted) {
midletStarted = true;
//Your code
}
}
This way you can track midlet state changes. But in fact it is better that you don't use this method at all and use constructor instead.
Oh, by the way, I don't think that there are some multiple instances or something like that, this is merely a JVM error.
Maybe you did something that made the runtime call pauseApp() and then when you set the focus to the app the runtime called startApp() again.
Put logging in pauseApp() and see what happens.

Resources