Not able to display the progress bar using threading concept? - c

I am trying to show a progress bar while my process is going on...in my application there will be a situation where I gotta read files and manipulate them(it will take some time to complete)..want to display a progress bar during this operation..the particular function I am calling is an win 32 ...so if you check my code below ...I am able to display the progressbar but it doesnt show any progress..actually its not doing any further process...Please help me..thanks in advance
//my function
int Myfunction(....)
{
MSG msg;
HWND dialog = CreateWindowEx(0,WC_DIALOG,L"Proccessing...",WS_OVERLAPPEDWINDOW|WS_VISIBLE,
600,300,280,120,NULL,NULL,NULL,NULL);
HWND pBar = CreateWindowEx(NULL,PROGRESS_CLASS,NULL,WS_CHILD|WS_VISIBLE,40,20,200, 20,
dialog,(HMENU)IDD_PROGRESS,NULL,NULL);
SendMessage(pBar,PBM_SETRANGE,0,MAKELPARAM(0,noOfFile));
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
Dispatch(&message);
}
HANDLE getHandle = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)SetFilesForOperation(...),
NULL,NULL,0);
}
LPARAM SetFilesForOperation(...)
{
for(int index = 0;index < noOfFiles; index++)
{
*checkstate = *(checkState + index);
if(*checkstate == -1)
{
*(getFiles+i) = new TCHAR[MAX_PATH];
wcscpy(*(getFiles+i),*(dataFiles +index));
i++;
}
else
{
(*tempDataFiles)->Add(*(dataFiles+index));
*(checkState + localIndex) = *(checkState + index);
localIndex++;
}
PostMessage(pBar,PBM_SETPOS,(WPARAM)index,0);
}
}

I suspect the problem is that you're creating the thread after your app exits - if you move the call to CreateThread above the message pump it may work better.

I prefer to use QT over MFC. Here's how I would use it to answer your question:
Use form designer to create a dialog, and use AfxBeginThread(someFunc, param) to create a thread.
In someFunc, use SendMessage to tell the dialog about the progress.
sample here:
http://www.tek-tips.com/faqs.cfm?fid=5162

Related

Why does focusing a TextBox speed up another thread's progress?

Hello Stackoverflowers!
I have a strange situation here. I wrote a small C# tool, to measure the time it takes to send a request via usb and wait until the response arrives. The communication is no problem, nor are the devices.
I put a simple TextBox on the GUI together with a "Start" button.
Pressing "Start" starts a thread with a loop (loops defined in the TextBox) sending requests and receiving the answers. In the GUI thread you can see a progress bar showing the status.
When I pressed "Start" I measured around 15 ms per command and response (in average) which is quite a long time.
When I pressed "Start" and clicked inside the TextBox (only setting the cursor inside), the worker thread ran through with an average time of 1.6 ms per command and response.
This is reproducible in my case. I even put in a new, totally useless TextBox. When clicking inside, the thread speeds up, when I focus another element, like a slider, the thread slows down again.
Has anyone ever heard about something like that and can explain to me, why this happens? And even better, how I can avoid this behavior?
FYI:
- I tried both BackgroundWorker and Thread, same behavior.
- For taking the times, I'm using .NET's stopwatch.
- Executing the measurement method in the GUI thread changes nothing. EDIT: Tried again and everything's as it should be. But now I have the problem, that the GUI freezes, since I'm working in its thread.
- Removing the progress bar changes nothing.
Thanks a lot!
EDIT:
private void tbAmount_Copy_PreviewKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
if (String.IsNullOrEmpty(tbDevAddrTime.Text))
return;
pbTimeMeasure.Value = 0;
worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(StartTimeMeasureHandler);
worker.RunWorkerAsync();
}
}
private void StartTimeMeasure()
{
int address = 1;
int loops = 1;
DispatchIfNecessary(() =>
{
address = Convert.ToInt32(tbDevAddrTime.Text);
loops = Convert.ToInt32(tbAmount_Copy.Text);
pbTimeMeasure.Maximum = loops;
});
System.Diagnostics.Stopwatch stopwatchLong = new System.Diagnostics.Stopwatch();
System.Diagnostics.Stopwatch stopwatchShort = new System.Diagnostics.Stopwatch();
var cmd = String.Format(":{0:X3}4010200300000000\r", RequestAddress + address);
for (int i = 0; i < loops; i++)
{
stopwatchLong.Start();
//SND
_canbus.Write(cmd, cmd.Length, ref _bytesWritten);
stopwatchShort.Start();
Thread.Sleep(1);
//RCV
var answer = ReadContent();
stopwatchShort.Stop();
stopwatchLong.Stop();
DispatchIfNecessary(() =>
{
pbTimeMeasure.Value++;
});
}
Double resLong = Convert.ToDouble(stopwatchLong.ElapsedMilliseconds);
Double resLongAvg = resLong / loops;
Double resShort = Convert.ToDouble(stopwatchShort.ElapsedMilliseconds);
Double resShortAvg = resShort / loops;
DispatchIfNecessary(() =>
{
lbTotalResLong.Content = resLong.ToString();
lbTotalResShort.Content = resShort.ToString();
int length = 5;
if (resLongAvg.ToString().Length < 5)
{
length = resLong.ToString().Length;
}
if (resShortAvg.ToString().Length < length)
{
length = resShortAvg.ToString().Length;
}
lbAvgResLong.Content = resLongAvg.ToString().Substring(0,length);
lbAvgResShort.Content = resShortAvg.ToString().Substring(0,length);
});
}

How to make a button where you can import your own music on processing?

I am looking for a way to make a type of import button where users can import their music from their folder. I've got no idea on how to do this so any tips would be grateful.
Here is something to get you going:
float buttonX;
float buttonY;
float buttonW;
float buttonH;
void setup() {
textSize(24);
frame.setResizable(false);
background(255);
size(600, 200);
fill(0);
stroke(0);
noFill();
buttonW = 200;
buttonH = 50;
buttonX = width - width/2 - buttonW/2;
buttonY = height/2 - buttonH/2;
}
void draw() {
background(255);
fill(0);
rectMode(CORNER);
rect(buttonX, buttonY, buttonW, buttonH);
fill(255);
textAlign(LEFT);
text("Import File", buttonX+35, buttonY+30);
}
void mouseClicked() {
if (mouseX>buttonX && mouseX < buttonX+buttonW && mouseY > buttonY && mouseY < buttonY+buttonH) {
selectInput("Import music file", "fileSelected");
}
}
/* Taken from Processing.org */
void fileSelected(File selection) {
if (selection == null) {
println("Window was closed or user hit cancel");
} else {
println("User selected " + selection.getAbsolutePath());
}
}
Notice some things here. The button is simply a rect that is drawn on the screen and then the click is bound within the limit of the rect, which in effect creates a button. I am showing this here so you can understand that you can create a GUI with the simplest and the most basic objects available to you in Processing. This is a very simple sketch that doesn't do anything other than give you a file browser (check Processing docs for that) and prints the path of the file you choose or writes out a message if you hit cancel. What you do with this is up to you. Have fun with it.
Once you're done playing around and want to see what others have done and what some of the GUIs made by others look like, go to this page and check out the GUI section: http://www.processing.org/reference/libraries/ (this is only to see how they've implemented their buttons, not for the file browser).

GeckoFX - WinForms - javascript:print()

i just created a win form app
with a Gecko.GeckoWebBrowser on it
when i navigate to a page with a anchor that has the href attribute set to
javascript:print() and click on it, the print dialog is displayed, but it turns out that when i hit cancel button on that dialog
the Gecko.GeckoWebBrowser is destroyed , i mean the control receives a WM_DETROY message
any clue of what is could be happen here?
how i can prevent it?
i modified the gecko fx Gecko.GeckoWebBrowser windows procedure and catch and bypass that windows message but it seems that is not helping
btw i am using xulrunner-11.0.en-US.win32 and geckofx-11.dll
regards
From looking at the firefox code, It looks like firefox is sending the WM_DESTROY message.
nsPrintingPromptService::ShowPrintDialog(nsIDOMWindow *parent, nsIWebBrowserPrint *webBrowserPrint, nsIPrintSettings *printSettings)
{
NS_ENSURE_ARG(parent);
HWND hWnd = GetHWNDForDOMWindow(parent);
NS_ASSERTION(hWnd, "Couldn't get native window for PRint Dialog!");
return NativeShowPrintDialog(hWnd, webBrowserPrint, printSettings);
}
nsresult NativeShowPrintDialog(HWND aHWnd,
nsIWebBrowserPrint* aWebBrowserPrint,
nsIPrintSettings* aPrintSettings)
{
PrepareForPrintDialog(aWebBrowserPrint, aPrintSettings);
nsresult rv = ShowNativePrintDialog(aHWnd, aPrintSettings);
if (aHWnd) {
::DestroyWindow(aHWnd);
}
return rv;
}
I'm not sure why it would do this.
Some options to fix this:
turn on "print.always_print_silent"
provide and register your own nsIPrintingPromptService
provide and register your own nsIWindowWatcher service.
The nsIWindowWatcher way looks like the proper way to do this looking at GetHWNDForDOMWindow:
HWND
nsPrintingPromptService::GetHWNDForDOMWindow(nsIDOMWindow *aWindow)
{
nsCOMPtr<nsIWebBrowserChrome> chrome;
HWND hWnd = NULL;
// We might be embedded so check this path first
if (mWatcher) {
nsCOMPtr<nsIDOMWindow> fosterParent;
if (!aWindow)
{ // it will be a dependent window. try to find a foster parent.
mWatcher->GetActiveWindow(getter_AddRefs(fosterParent));
aWindow = fosterParent;
}
mWatcher->GetChromeForWindow(aWindow, getter_AddRefs(chrome));
}
if (chrome) {
nsCOMPtr<nsIEmbeddingSiteWindow> site(do_QueryInterface(chrome));
if (site)
{
HWND w;
site->GetSiteWindow(reinterpret_cast<void **>(&w));
return w;
}
}

Going through a Pivot control really fast crashes

I have a pivot control and a button which does selectedIndex++ and when the selectedIndex has gone passed the last entry it will open up a messagebox asking the user if they want to quiz.
But during testing if you spam the button it will create a 0x8000ffff error when you open the MessageBox.
How do I stop this from happening? is it something to do with the ui thread being too busy or continuing to move the pivot? is the button event still running after I try to navigate out of the page?
this is what the code that does the selectedIndex++
void gotoNextQuestion()
{
if (quizPivot.SelectedIndex < App.settings.currentTest.Questions.Count() - 1)
{
//xScroll -= scrollAmount;
//moveBackground(xScroll);
if (!stoppedPaging)
{
quizPivot.SelectedIndex++;
}
//App.PlaySoundKey("next");
}
else
{
if (App.settings.testMode == App.TestModes.TrainingRecap)
{
MessageBoxResult result;
if (countAnsweredQuestions() == App.settings.currentTest.Questions.Count())
{
stoppedPaging = true;
result = MessageBox.Show("You have reviewed every training question, would you like to go back to the main menu?", "Training Over", MessageBoxButton.OKCancel);
stoppedPaging = false;
if (result == MessageBoxResult.OK)
{
positionableSpriteRadioButton.IsAnswered -= new Action<bool>(Answers_IsAnsweredCompleted);
spriteRadioButton.IsAnswered -= new Action<bool>(Answers_IsAnsweredCompleted);
App.settings.currentTest = null;
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
return;
}
}
}
else
{
MessageBoxResult result;
if (countAnsweredQuestions() == App.settings.currentTest.Questions.Count())
{
stoppedPaging = true;
result = MessageBox.Show("You have answered all of the questions, are you sure you want to finish?", "Are you sure you want to finish?", MessageBoxButton.OKCancel);
stoppedPaging = false;
}
else
{
checkFinishConditions();
}
}
quizPivot.SelectedIndex = 0;
//App.PlaySoundKey("begin");
}
App.settings.currentTest.currentQuestion = quizPivot.SelectedIndex;
}
Well, one thing is for sure
positionableSpriteRadioButton.IsAnswered -= new Action<bool>(Answers_IsAnsweredCompleted);
That isn't going to work. You're creating a new Action every time. So nothing will have the same reference id, and thus nothing will be removed.
Instead you should remove the Action<bool> and simply subscribe/unsubscribe with
positionableSpriteRadioButton.IsAnswered -= Answers_IsAnsweredCompleted;
And when you subscribe
positionableSpriteRadioButton.IsAnswered += Answers_IsAnsweredCompleted;
That way you can actually remove it again.
But I would recommend you not to use a pivot for this type of "wizard". It's abuse of the control, and going to give a really poor user experience.
Also, just because you navigate to another page, it doesn't mean the code stops running. All code in the same expression is executed, unless you add a return statement after the call to NavigationService.Navigate.
Also, always make sure that Navigation is on the UI thread by wrapping all calls to NavigationService.Navigate in a call to Dispatcher.BeginInvoke.

Find Control Name from non-UI thread

I found a nice Find Name code snippet that I'm using in a WPF solution:
public static T FindVisualChildByName<T>(DependencyObject parent, string name) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
string controlName = child.GetValue(Control.NameProperty) as string;
if (controlName == name)
{
return child as T;
}
else
{
T result = FindVisualChildByName<T>(child, name);
if (result != null)
return result;
}
}
return null;
}
But this only works if I am on the UI thread.
I have another thread that is playing an audio file with an end sync. I want to use the code above to set a dep property on the ui thread, but I keep getting a cross-thread error.
Even trying a simple:
SoundFXPad selectedSoundFXPad = (SoundFXPad)m_parent.FindName("panelC" + numbervar);
Gives me the same error
All the other thread-safe WPF Dispatcher-Invoke codes I have seen assume you already know the name of the control. Is there a way to use the either code above in a thread-safe way to affect a UI control from another thread where the name needs to be "found"?
Thank You!
There's generally one UI thread per application (generally; you can create multiple, but it's not common). So you don't need the control name to find the dispatcher - try this:
Application.Current.Dispatcher.Invoke(new Action(
delegate {
// Put code that needs to run on the UI thread here
}));

Resources