|
Works perfekt, thanks alot
void blabla()
{
WebClient laddaner = new WebClient();
laddaner.OpenReadCompleted += new OpenReadCompletedEventHandler(laddaner_OpenReadCompleted);
laddaner.OpenReadAsync(new Uri("http://adress.com"));
}
void laddaner_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error.Message == null)
{
StreamReader sr = new StreamReader(e.Result);
string s = sr.ReadToEnd();
}
else
MessageBox.Show(e.Error.Message);
}
|
|
|
|
|
I have 2 forms.
disable some buttons;
form1 call some bool function on form2(via a delegate).
this function will print some stuff on a textbox in form1 via a cross thread handler.
if the function return true then enable the buttons.
simple enough. but vs2005 give me this error:
"Cross-thread operation not valid: Control 'button1' accessed from a thread other than the thread it was created on."
Does anyone knows what is going here? And how i can solve it?
Donkaiser
|
|
|
|
|
oh one more thing my program is in C# so i guess if i post it in this forum it may help.
Donkaiser
|
|
|
|
|
see: System.Windows.Forms.Control.Invoke() method and BeginInvoke
"What classes are you using ? You shouldn't call stuff if you have no idea what it does" Christian Graus in the C# forum
led mike
-- modified at 14:22 Monday 22nd May, 2006
Also see the forum thread about 5 positions below this one on the same subject.
|
|
|
|
|
well i just after wanna do like
button1.enable = false;
if(somedelegate funcOnform2())
{
button1.enable = true;
}
and the IDE gave me the error at button1.enable = true;
Donkaiser
|
|
|
|
|
donkaiser wrote: well i just after wanna do like
Whatever. good luck
"What classes are you using ? You shouldn't call stuff if you have no idea what it does" Christian Graus in the C# forum
led mike
|
|
|
|
|
You can only access Form1 on the thread it was created on. You can only access Form2 on the thread it was created on. And so on. This is the reason you're getting an error.
In order to solve this, you need to actually perform the work on the correct thread. To do this, you can use form.Invoke, which will bring the work onto the correct thread for that form.
ThreadStart functionThatChangesEnabledState = delegate()
{
form1.Enabled = true;
};
form1.Invoke(functionThatChangesEnabledState);
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 Judah,
Do i need to create a new instant of my form1? because VS2005 throws me this error:
"Object reference not set to an instance of an object." at form1.Invoke(functionThatChangesEnabledState);
Donkaiser
|
|
|
|
|
|
Never mind, I solved it by putting it on form1 instead. and inside the ThreadStart i perform watever on the controls.
Thx alot. I hope this will help other people.
Donkaiser
|
|
|
|
|
I created a custom SOAP header to handle a custom token that contains encrypted user data, encrypted key, and Initialization Vector for the cipher. I can send the token to the Web Service, but how do I send it back to the client with the new verification data, key, and Initialization Vector? How do I access the data contained in the token on the client side?
ICP-Fan
|
|
|
|
|
Hello all,
I have an application written in VS2003 and I recently upgraded to VS2005. There were a number of threading problems that needed to be resolved (and were), however, I am stuck trying to fix the next issue that cropped up.
I have a vertical scrollbar in my form that is anchored on the top and bottom only. I move it so it is to the left of a splitter when the splitter is moved. It all worked perfectly in VS 2003. In VS 2005 it is acting so bizarre that it has to be a bug in VS 2005. When you resize the window just up/down it works properly, if you resize diagonally (lower right corner) the scrollbar jumps all over and has varying lengths from longer than the form to 1/2 or 1/4 of the form height.
Also I am setting the .min and .max of the scrollbar and that is also not working properly. For example I set the min and max to be 0-10 and yet the scrollbar only allows .Value of 0 or 1?
Has anybody else seen this? Is it a conversion problem going from 2003 to 2005? I tried deleting and re-creating the scrollbar but it didn't fix anything. Since I don't ever do anything other than set the .Left field how can it be sizing too tall or too short? I checked the properties and it is anchored on the top and bottom.
Thanks,
Rick Wirch
P.S. I have been a developer for over 20 years, so I am not a newbie. However, I have only been using C# for a couple of years (C++ for many moons before).
-- modified at 12:29 Monday 22nd May, 2006
|
|
|
|
|
Hi everybody!
I'm new on C# programming. I have a main form in my Windows applications that contains other form as a Explorer of folders. I don't want to allow to drag the Explorer form (FrmExplorer). FrmExplorer has a TreeView. I have been looking for information about it and have written the following code:
public partial class FrmExplorer : Form
{
public FrmExplorer(string fileName)
{
InitializeComponent();
//To cancel dragging the form
this.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.FrmExplorer_CancelDrag);
this.DragEnter += new System.Windows.Forms.DragEventHandler(this.FrmExplorer_EnterDrag);
this.DragOver += new System.Windows.Forms.DragEventHandler(FrmExplorer_DragOver);
this.AllowDrop = false;
}
private void FrmExplorer_CancelDrag(object sender, QueryContinueDragEventArgs e)
{
e.Action = DragAction.Cancel;
}
private void FrmExplorer_EnterDrag(object sender, System.Windows.Forms.DragEventArgs e)
{
e.Effect = DragDropEffects.None;
}
private void FrmExplorer_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
{
// Determine whether string data exists in the drop data. If not, then
// the drop effect reflects that the drop cannot occur.
if (!e.Data.GetDataPresent(typeof(System.String)))
{
e.Effect = DragDropEffects.None;
return;
}
}
}
I have set the method FrmExplorer_CancelDrag in FrmExplorer Properties in the event QueryContinueDrag. But I still cannot reach the method FrmExplorer_CancelDrag when dragging the form to cancel that action.
Does anybody can help me to know what I'm doing wrong or what is it missing?
Thanks a lot in advance,
Elvia
|
|
|
|
|
Hi guys
I'm having some difficulty with the System.Threading.ManualResetEvent.
My function is listed below. Excuse the relatively large function; scroll down towards the end and you'll see the line I'm having trouble with.
private static bool WaitForCompletionOrTimerExpiration(Function method, int timeout)
{
using (ManualResetEvent threadWaitHandle = new ManualResetEvent(false))
{
bool hasFinishedExecutingMethod = false;
int hasSignalled = 0;
TimerCallback timerCallback = delegate(object state)
{
int originalValueOfHasSignalled = Interlocked.CompareExchange(ref hasSignalled, 1, 0);
if (originalValueOfHasSignalled == 0)
{
threadWaitHandle.Set();
}
};
Exception methodException = null;
WaitCallback threadPoolMethod = delegate(object state)
{
try
{
method();
}
finally
{
int originalValueOfHasSignalled = Interlocked.CompareExchange(ref hasSignalled, 1, 0);
if (originalValueOfHasSignalled == 0)
{
hasFinishedExecutingMethod = true;
threadWaitHandle.Set();
}
}
};
using (Timer timer = new Timer(timerCallback, null, timeout, Timeout.Infinite))
{
ThreadPool.QueueUserWorkItem(threadPoolMethod);
threadWaitHandle.WaitOne();
}
return hasFinishedExecutingMethod;
}
}
Notice the WaitOne() call; sometimes this call blocks forever! In what circumstance will thread WaitOne() call block forever?
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
|
|
|
|
|
Judah Himango wrote: threadWaitHandle.Set();
Shouldn't that be Reset?
Here is what I gather:
- you start at a off state (shouldnt that be on?)
- the timer starts before the ThreadPool submission
- the ThreadPool start time is normally slow
Why not use the WaitOne(Int32, Boolean) overload? You wouldnt have to use a timer then.
Hope it helps
|
|
|
|
|
I'm not all too familiar with the WaitHandle; so you'll have to pardon my lack of knowledge there.
Before you posted I realized I can use the WaitOne overload that takes a time period which to wait, thus making my timer code redundant. So I've removed the timer code and opted to use the WaitOne overload.
However, you brought up something I'm not understanding. Should it be Reset instead of Set? I'm starting with an off state and switching to an on state. You're saying that's incorrect usage? I guess I'm not understanding why it would matter either way, as Set() seems to signal the waiting thread correctly.
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
|
|
|
|
|
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
|
|
|
|
|