|
I just looked at some of my code I used it before, it appears Set() is correct .
The only difference I can see is that I explicitly call Reset() before starting the thread. Everything else seems the same. Perhaps that is the magic required Hope it works!
PS: If you want to, I can mail you the code, its part of xacc.ide. (if u have the source, Build\Action.cs:1005).
|
|
|
|
|
|
|
I'm having problems getting my head around raising event on the UI thread, and haven't been able to find an example for my particular situation. I've written a homespun class that exposes an integer property, and raises an event whenever it changes:
public class Engine<br />
{<br />
public event EventHandler ProgressChanged;<br />
private int progress;<br />
<br />
public Engine ()<br />
{<br />
progress = 0;<br />
}<br />
<br />
public int Progress<br />
{ get { return progress; } }<br />
<br />
public void Run ()<br />
{<br />
for(int index = 0; index < 100; index++)<br />
{<br />
Thread.Sleep(1000);<br />
progress++;<br />
if(ProgressChanged != null)<br />
ProgressChanged(this,new EventArgs());<br />
}<br />
}<br />
}
I want to bind this property to a ProgressBar in my UI.
Engine obj = new Engine();<br />
progressBar.DataBindings.Add("Value",obj,"Progress");<br />
Thread thread = new Thread(new ThreadStart(obj.Run));<br />
thread.Start();
But of course I can't update the ProgressBar from my worker thread, that's something I understand and accept. I think I should be using BeginInvoke to raise the event, but I'm lost as to how to do this.
Any ideas? Thanks in advance, Iain.
|
|
|
|
|
First of all, you can update your progress bar from a worker thread. Second of all, an event is not thrown when you do a ++ on progress.
Change your property to something like this:
public int Progress {
get { return progress; }
set {
progress = value;
if (ProgressChanged != null)
ProgressChanged(this, new EventArgs());
}
}
Then you could write a Progress++ in your code and the event will fire.
But what you're really trying to do is tell your progress bar to increment. What I do for this is add this delegate to my form class:
delegate void ProgressBarStep();
Then I have a method that's called by my worker thread:
private void WorkerThreadMethod()
{
...
ProgressBarStep progBarStep = delegate() { progressBar.PerformStep(); };
...
Invoke(progBarStep);
...
}
Notice that I use an anonymous method and call Invoke on the form itself. This will let you call methods on the main thread from another thread. Use the invoke inside your loop.
Hope that makes sense.
www.logifusion.com
-- modified at 12:06 Monday 22nd May, 2006
|
|
|
|
|
Thanks Dustin for your input.
My main issue, which I didn't expand on in my original post (apologies!) is that I don't know in advance which UI control or controls will be bound to my Engine object. As such I want to avoid completely, or as far as possible, directly calling methods on the UI controls. In fact I really want my Engine class to be generic so that I can use it in a number of places, and bind different UI controls to different Engine objects.
If you can offer any further advice I would really appreciate your input.
Thanks again, Iain.
|
|
|
|
|
One thing you can do is pass an object to the Engine class that allows the Engine to raise events on the UI thread.
Here's how you can do it:
using System.Threading;
public class Engine
{
public event EventHandler ProgressChanged;
private int progress;
private SynchronizationContext eventRaisingContext;
public Engine (SynchronizationContext uiContext)
{
this.eventRaisingContext = uiContext;
}
public int Progress
{ get { return progress; } }
public void Run ()
{
for(int index = 0; index < 100; index++)
{
Thread.Sleep(1000);
progress++;
RaiseEventOnCorrectThread();
}
}
}
private void RaiseEventOnCorrectThread()
{
eventRaisingContext.Post(RaiseEvent, null);
}
private void RaiseEvent(object state)
{
if(ProgressChanged != null)
ProgressChanged(this,new EventArgs());
}
}
And then in your UI code, just supply a synchronization context:
Engine obj = new Engine(System.Windows.Forms.WindowsFormsSynchronizationContext.Current);
progressBar.DataBindings.Add("Value",obj,"Progress");
Thread thread = new Thread(new ThreadStart(obj.Run));
thread.Start();
Tech, life, family, faith: Give me a visit.
I'm currently blogging about: Islamic Domination: Coming to a Jewish state near you!
The apostle Paul, modernly speaking: Epistles of Paul
Judah Himango
|
|
|
|
|
Thanks Judah for your input.
I think I can see how passing in a context allows me to call methods on an object created in a different thread. However my main issue, which I didn't expand on in my original post (apologies!) is that I don't know in advance which UI control or controls will be bound to my Engine object. So with this context approach I would need some way for each control to specify it's context. Or would all the UI controls be created in the same thread, and therefore have the same context?
I really want my Engine class to be generic so that I can use it in a number of places, and bind different UI controls to different Engine objects. I'd anticipated that I'd need to use BeginInvoke on my ProgressChanged method. If you can offer any further advice I would really appreciate your input.
Thanks again, Iain.
|
|
|
|
|
In a typical situation, all--or virtually all--UI controls will be created from the same thread. Thus, the solution posted should work fine.
If you happen to have controls created on different threads, you can still make this work:
Engine engine = new Engine(WindowsFormsSynchronizationContext.Current);
engine.RunOnSeperateThread();
Engine engine = new Engine(WindowsFormsSynchronizationContext.Current);
engine.RunOnSeperateThread();
This should work as well.
If the Engine class is *always* created on the UI, but the Run() method is *always* spawning a background thread to do the real work, you might want to investigate the System.ComponentModel.BackgroundWorker. The BackgroundWorker is nice as it lets you do the following:
worker.DoWork += someMethodToRunOnBackground;
worker.ProgressChanged += someMethodToRunOnUIThreadWhenProgressReported;
worker.RunWorkerCompleted += someMethodToRunOnUIThreadWhenFinished;
worker.RunWorkerAsync();
This way is quite generic and pretty straightforward. Your DoWork handler will get run on a background thread. Your ProgressChanged handler will get called on your UI thread. Your RunWorkerCompleted will get called on the UI thread. Nice stuff, I suggest you check it out if you haven't already. You could use the BackgroundWorker internally in your Engine class if you wanted to retain existing code.
Tech, life, family, faith: Give me a visit.
I'm currently blogging about: Islamic Domination: Coming to a Jewish state near you!
The apostle Paul, modernly speaking: Epistles of Paul
Judah Himango
|
|
|
|
|
Hi all,
I need some articles/materials/presentation for the following topics
1. Thread synchronization
2. basics of Appdomain,STA,MTA
3. Thread Safety/Cross thread calling
4. XML handling reading/writing/encrypting xml
If anybody has plese share..
TIA
Srini
|
|
|
|
|
|
Thanks for ur reply.
Yes i did some search on codeproject and google. even i read some of the articles.but still i am not able understand the mentioned concepts. If you have something particularly that could explains the mentioned things please share.
Thanks
Srini
|
|
|
|
|
Hi,
I am trying to run a C# code to generate a dll file that I will need for a pocket PC appication. When I build the code, I am getting 107 errors that are similar to this one:
Error 1 The type or namespace name 'SymmetricAlgorithm' could not be found (are you missing a using directive or an assembly reference?) C:\Documents and Settings\msolh\Desktop\Security\Security\Cryptography\RC4.cs 46 30 Security
For instance in this error I checked for 'SymmetricAlgorithm' and I found that it is part of mscorlib and namespace system.Security.cryptography. The library and the namespace are both included in my project but still it is giving me the same errors.
If you had this problem before, please help.
|
|
|
|
|
Do you compile your project for the compact framework? According to MSDN this class is supported only by the 2.0 version of the compact framework.
regards
modified 12-Sep-18 21:01pm.
|
|
|
|
|
Thanks,
The problem is solved it turned out that I was running a 1.0 version of compact framework.
But know I am stuck into another problem:
It turned out some of the classes I am using are not supported for windows mobile. I donot know how to subtitute them. One of the classes for example is:
DeriveBytes
|
|
|
|
|
msolh wrote: It turned out some of the classes I am using are not supported for windows mobile. I donot know how to subtitute them.
Yeah, that's unfortunately something you had to take care of while designing your app.
You only have the option to rewrite this class my yourself of find a substitute class which provides similar functionality.
regards
modified 12-Sep-18 21:01pm.
|
|
|
|
|
Is it possible to fill listview with an one or more dimensional array by using databinding method?
|
|
|
|
|
hi all,
is it possible to hide (and show) unwanted tabs when dealing with a specific tab ?
let's say i've a tabcontrol with 5 pages (first page is only required for a while) and with a button click i want to hide all other 4 pages ?
then i make them show again when i need them ?
|
|
|
|
|
If you are using VS2005, you can do it as follows:
create dynamic tabs array through code.
Create each tab and add to the tab list, when ever you need to hide you can stop loading those tabs.
Try and check, else i will give you sample code
|
|
|
|
|
I suppose the
TabControl1.TabPages(1).Visible = False Wont work in .Net Framework 1.1. As a work around you use
TabControl1.TabPages.Add() and TabControl1.TabPages.Remove() as when you require tab pages
|
|
|
|
|
yes,
hide and show or Visible =true or false properties are not available for TabPages, Only availble option is Remove and add again.
RemoveAt(...) and RemoveByKey(...) are availble and then we can add at any time.
Ravi
|
|
|
|
|
I am having .NET framework1.1
I need to compile C# windows project from the command line
I have compiled the code in the following way
csc /out:exe *.cs
It is showing the error missing resources files.
In the project i am having one image two text boxes and a listbox.
I have used System.Globalization for German language culture to change date and time format.
Can any one help me what are the exact parameters do i need to pass to the command "CSC".
|
|
|
|
|
|
AFAIK, you will need the Resource compiler, that's only available in the .NET SDK.
|
|
|
|
|
I am using a third party SNMP component. I create this component at run-time in a C# class.
I am wondering if there is someway I can use event handlers for this control in that class.
|
|
|
|