473,320 Members | 2,029 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

C# threading & events

Hi NG.

I'm creating a little app. that has to use a 3rd party API.
The functions in this API has no return value but trigger events like OK
or NOT OK with event args.

Where I need to use this API I must have a synchrone modul so I need to
force a synchrone look to this asynchrone model of the API.

I was thinking this would call for some waiting for events and since I
don't wanna make a loop eat all the cpu power I was thinking of using a
few threads to accomplish this.

It's giving me some trouble though I'm aware it's a pretty common and
simple scenario.

I was hoping maybe somone here could lend me a hand.

What I need is as said, to make some code that uses the API but my code
has to be synchrone while the API is not.

So I can do somthing like:
--------------------------
public MyClass
{
private bool InProcess;
private bool ItWentWell;

public bool Function1()
{
InProcess = true;

APIClass apic = new APIClass();

apic.FunctionAPI1_Success += EventHandler(FunctionOK);
apic.FunctionAPI1_Failed += EventHandler(FunctionERROR);

apic.FunctionAPI1();

...
Wait for InProcess to change from TRUE to FALSE.
Once this happens, return ItWentWell.
}

public void FunctionOK()
{
Inprocess = false;

ItWentWell = true;
}

public void FunctionERROR()
{
InProcess = false;

ItWentWell = false;
}
}

//--- somwhere like the Main of a console app. ---
MyClass mc = new MyClass();

if(mc.Function1())
{
Consile.WriteLine("API call went well.");
}
else
{
Consile.WriteLine("API call went bad.")
}
--------------------------

I'm aware that the above doesn't work, it's only to give a picture of
what I'm trying to accomplish. Somwhere around the part with the waiting
for the event to occur should most likely be using a new thread not to
eat all the cpu power, but I can't get the things I've tried to work.

Any help would be much appreciated, thanks :)

/Aidal
Jan 11 '07 #1
12 2217

"Aidal" <no@address.comwrote in message
news:45*********************@dreader2.cybercity.dk ...
Hi NG.

I'm creating a little app. that has to use a 3rd party API.
The functions in this API has no return value but trigger events like OK
or NOT OK with event args.

Where I need to use this API I must have a synchrone modul so I need to
force a synchrone look to this asynchrone model of the API.

I was thinking this would call for some waiting for events and since I
don't wanna make a loop eat all the cpu power I was thinking of using a
few threads to accomplish this.
Use the EventWaitHandle class built in to .NET. Or convert your algorithm
to a state machine.
Jan 11 '07 #2
Aidal skrev:
Hi NG.

I'm creating a little app. that has to use a 3rd party API.
The functions in this API has no return value but trigger events like OK
or NOT OK with event args.

Where I need to use this API I must have a synchrone modul so I need to
force a synchrone look to this asynchrone model of the API.

I was thinking this would call for some waiting for events and since I
don't wanna make a loop eat all the cpu power I was thinking of using a
few threads to accomplish this.

It's giving me some trouble though I'm aware it's a pretty common and
simple scenario.

I was hoping maybe somone here could lend me a hand.

What I need is as said, to make some code that uses the API but my code
has to be synchrone while the API is not.

So I can do somthing like:
--------------------------
public MyClass
{
private bool InProcess;
private bool ItWentWell;

public bool Function1()
{
InProcess = true;

APIClass apic = new APIClass();

apic.FunctionAPI1_Success += EventHandler(FunctionOK);
apic.FunctionAPI1_Failed += EventHandler(FunctionERROR);

apic.FunctionAPI1();

...
Wait for InProcess to change from TRUE to FALSE.
Once this happens, return ItWentWell.
}

public void FunctionOK()
{
Inprocess = false;

ItWentWell = true;
}

public void FunctionERROR()
{
InProcess = false;

ItWentWell = false;
}
}

//--- somwhere like the Main of a console app. ---
MyClass mc = new MyClass();

if(mc.Function1())
{
Consile.WriteLine("API call went well.");
}
else
{
Consile.WriteLine("API call went bad.")
}
--------------------------

I'm aware that the above doesn't work, it's only to give a picture of
what I'm trying to accomplish. Somwhere around the part with the waiting
for the event to occur should most likely be using a new thread not to
eat all the cpu power, but I can't get the things I've tried to work.

Any help would be much appreciated, thanks :)

/Aidal
Anyone have an actual code example or a link to one where:

Class1.FunctionA calls Class2.FunctionB which will (at some point)
trigger an event.
Class1.FunctionA must not return before the event occuers because it
needs to base its return value on what the event "said" like true/false.

Aka Class1.FunctionA must wait for the event triggered by
Class2.FunctionB to occuer before it knows what to return.

As mentioned above I assume some threading should be used but I'm not sure.

/Aidal
Jan 12 '07 #3
Like so?

using System;
using System.Threading;

static class Program
{
static void Main()
{
new ClassA().MethodA();
}
}
class ClassA
{
public void MethodA()
{
ClassB b = new ClassB();
string theSomething = "";
ManualResetEvent evt = new ManualResetEvent(false);
b.SomethingHappened += delegate
{
theSomething = b.TheSomething;
evt.Set();
};
ThreadPool.QueueUserWorkItem(delegate {
b.MethodB();
});
evt.WaitOne();
Console.WriteLine(theSomething);
}
}
class ClassB
{
public event EventHandler SomethingHappened;
private string _theSomething;
public string TheSomething {get {return _theSomething;}}
protected void OnSomethingHappened()
{
EventHandler handler = SomethingHappened;
if (handler != null) handler(this, EventArgs.Empty);
}
public void MethodB()
{
_theSomething = Console.ReadLine();
OnSomethingHappened();
}
}
Jan 12 '07 #4
Note: for brevity, in my example I didn't bother putting the "what
happened" into an event-arg subclass - but this would work identically
to the property approach; you may also wish to be "using" the
ManualResetEvent (since it is IDisposable).

As an alternative, note that you can also do this using locks to avoid
the (marginally more expensive) ManualResetEvent - but unless you are
high volume it might not be worth it; note to follow the logic here
requires a good understanding of "lock" (Monitor.Enter, Monitor.Exit),
Monitor.Wait and Monitor.Pulse...

public void MethodA() {
ClassB b = new ClassB();
string theSomething = "";
object sync = new object();
b.SomethingHappened += delegate {
theSomething = b.TheSomething;
lock (sync) {
Monitor.Pulse(sync);
}
};
lock (sync) {
ThreadPool.QueueUserWorkItem(delegate {
b.MethodB();
});
Monitor.Wait(sync);
}
Console.WriteLine(theSomething);
}
Jan 12 '07 #5
Marc Gravell skrev:
Like so?

using System;
using System.Threading;

static class Program
{
static void Main()
{
new ClassA().MethodA();
}
}
class ClassA
{
public void MethodA()
{
ClassB b = new ClassB();
string theSomething = "";
ManualResetEvent evt = new ManualResetEvent(false);
b.SomethingHappened += delegate
{
theSomething = b.TheSomething;
evt.Set();
};
ThreadPool.QueueUserWorkItem(delegate {
b.MethodB();
});
evt.WaitOne();
Console.WriteLine(theSomething);
}
}
class ClassB
{
public event EventHandler SomethingHappened;
private string _theSomething;
public string TheSomething {get {return _theSomething;}}
protected void OnSomethingHappened()
{
EventHandler handler = SomethingHappened;
if (handler != null) handler(this, EventArgs.Empty);
}
public void MethodB()
{
_theSomething = Console.ReadLine();
OnSomethingHappened();
}
}

I've tried to create your example but it appears to have syntax errors
around "b.SomthingHappened += delegate". :(

/Aidal
Jan 12 '07 #6
Marc Gravell skrev:
Like so?

using System;
using System.Threading;

static class Program
{
static void Main()
{
new ClassA().MethodA();
}
}
class ClassA
{
public void MethodA()
{
ClassB b = new ClassB();
string theSomething = "";
ManualResetEvent evt = new ManualResetEvent(false);
b.SomethingHappened += delegate
{
theSomething = b.TheSomething;
evt.Set();
};
ThreadPool.QueueUserWorkItem(delegate {
b.MethodB();
});
evt.WaitOne();
Console.WriteLine(theSomething);
}
}
class ClassB
{
public event EventHandler SomethingHappened;
private string _theSomething;
public string TheSomething {get {return _theSomething;}}
protected void OnSomethingHappened()
{
EventHandler handler = SomethingHappened;
if (handler != null) handler(this, EventArgs.Empty);
}
public void MethodB()
{
_theSomething = Console.ReadLine();
OnSomethingHappened();
}
}

The actual scenario is:
=======================
ClassAPI has a function
- void SendFile()
and the two events
- FileSendOK
and
- FileSendError

MyClass has the function
- bool SendFile()
which is to use the function ClassAPI.SendFile()

What I want to be able to do is:
--------------------------------
MyClass mc = new MyClass();

if(mc.SendFile())
{
do somthing when sending file is successful...
}
else
{
do somthing else when sending file fails...
}
---------------------------------

Which means MyClass.SendFile() must wait for one of the two events in
ClassAPI to occuer (due to the ClassAPI.SendFile call) before it returns.

/Aidal
Jan 12 '07 #7
Ah... 1.1... I was heavily using the "captured variable" feature of
anonymous methods as a means to share state between threads. Never
mind... it can be done the other way - it just takes more code. Note:
I hanve't tested this in 1.1, so it may need tweaking, but it should
be fairly close (may also need to lose "static" from "static class
Program"):

class ClassA
{
internal class MethodAState
{
private readonly ClassB B;
private readonly object Sync = new object();
private string _theSomething;
public MethodAState()
{
B = new ClassB();
B.SomethingHappened += new
EventHandler(B_SomethingHappened);
}
public string StartAndWaitMethodB()
{
lock (Sync)
{
ThreadPool.QueueUserWorkItem(new
WaitCallback(B_StartB));
Monitor.Wait(Sync);
return _theSomething;
}
}
void B_StartB(object state)
{
B.MethodB();
}

void B_SomethingHappened(object sender, EventArgs e)
{
lock (Sync)
{
_theSomething = B.TheSomething;
Monitor.Pulse(Sync);
}
}

}
public void MethodA()
{
MethodAState state = new MethodAState();
string value = state.StartAndWaitMethodB();
Console.WriteLine(value);
}
}
Jan 12 '07 #8
Previous post re-worked to handle two different events with differing
signatures (pretend that TheSomething is in the event-args <g>). Type
"boom" to get the new behaviour; the string could likewise be a
success bool:

using System;
using System.Threading;

class Program
{
static void Main()
{
new ClassA().MethodA();
}
}
class ClassA
{
internal class MethodAState
{
private readonly ClassB B;
private readonly object Sync = new object();
private string _theSomething;
public MethodAState()
{
B = new ClassB();
B.SomethingHappened += new
EventHandler(B_SomethingHappened);
B.SomethingElseHappened +=new
EventHandler(B_SomethingElseHappened);
}
public string StartAndWaitMethodB()
{
lock (Sync)
{
ThreadPool.QueueUserWorkItem(new
WaitCallback(B_StartB));
Monitor.Wait(Sync);
return _theSomething;
}
}
void B_StartB(object state)
{
B.MethodB();
}

void B_SomethingHappened(object sender, EventArgs e)
{
ReleaseCaller(B.TheSomething);
}
void B_SomethingElseHappened(object sender, EventArgs e)
{
ReleaseCaller("PANIC PANIC PANIC");
}
private void ReleaseCaller(string result)
{
lock (Sync)
{
_theSomething = result;
Monitor.Pulse(Sync);
}
}

}
public void MethodA()
{
MethodAState state = new MethodAState();
string value = state.StartAndWaitMethodB();
Console.WriteLine(value);
}
}
class ClassB
{
public event EventHandler SomethingHappened,
SomethingElseHappened;
private string _theSomething;
public string TheSomething { get { return _theSomething; } }
private void OnEvent(EventHandler handler)
{
if (handler != null) handler(this, EventArgs.Empty);
}
public void MethodB()
{
string value = Console.ReadLine();
if (value == "boom")
{
OnEvent(SomethingElseHappened);
}
else
{
_theSomething = value;
OnEvent(SomethingHappened);
}
}
}
Jan 12 '07 #9
Marc Gravell skrev:
Previous post re-worked to handle two different events with differing
signatures (pretend that TheSomething is in the event-args <g>). Type
"boom" to get the new behaviour; the string could likewise be a
success bool:

using System;
using System.Threading;

class Program
{
static void Main()
{
new ClassA().MethodA();
}
}
class ClassA
{
internal class MethodAState
{
private readonly ClassB B;
private readonly object Sync = new object();
private string _theSomething;
public MethodAState()
{
B = new ClassB();
B.SomethingHappened += new
EventHandler(B_SomethingHappened);
B.SomethingElseHappened +=new
EventHandler(B_SomethingElseHappened);
}
public string StartAndWaitMethodB()
{
lock (Sync)
{
ThreadPool.QueueUserWorkItem(new
WaitCallback(B_StartB));
Monitor.Wait(Sync);
return _theSomething;
}
}
void B_StartB(object state)
{
B.MethodB();
}

void B_SomethingHappened(object sender, EventArgs e)
{
ReleaseCaller(B.TheSomething);
}
void B_SomethingElseHappened(object sender, EventArgs e)
{
ReleaseCaller("PANIC PANIC PANIC");
}
private void ReleaseCaller(string result)
{
lock (Sync)
{
_theSomething = result;
Monitor.Pulse(Sync);
}
}

}
public void MethodA()
{
MethodAState state = new MethodAState();
string value = state.StartAndWaitMethodB();
Console.WriteLine(value);
}
}
class ClassB
{
public event EventHandler SomethingHappened,
SomethingElseHappened;
private string _theSomething;
public string TheSomething { get { return _theSomething; } }
private void OnEvent(EventHandler handler)
{
if (handler != null) handler(this, EventArgs.Empty);
}
public void MethodB()
{
string value = Console.ReadLine();
if (value == "boom")
{
OnEvent(SomethingElseHappened);
}
else
{
_theSomething = value;
OnEvent(SomethingHappened);
}
}
}

Thanks Marc :)

This example looks very interesting, I will try to apply the idea to my
code as soon as I get a free moment from other stuff.

/Aidal
Jan 15 '07 #10
You're welcome; best of luck
Jan 15 '07 #11
Aidal skrev:
Marc Gravell skrev:
>Previous post re-worked to handle two different events with differing
signatures (pretend that TheSomething is in the event-args <g>). Type
"boom" to get the new behaviour; the string could likewise be a
success bool:

using System;
using System.Threading;

class Program
{
static void Main()
{
new ClassA().MethodA();
}
}
class ClassA
{
internal class MethodAState
{
private readonly ClassB B;
private readonly object Sync = new object();
private string _theSomething;
public MethodAState()
{
B = new ClassB();
B.SomethingHappened += new EventHandler(B_SomethingHappened);
B.SomethingElseHappened +=new
EventHandler(B_SomethingElseHappened);
}
public string StartAndWaitMethodB()
{
lock (Sync)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(B_StartB));
Monitor.Wait(Sync);
return _theSomething;
}
}
void B_StartB(object state)
{
B.MethodB();
}

void B_SomethingHappened(object sender, EventArgs e)
{
ReleaseCaller(B.TheSomething);
}
void B_SomethingElseHappened(object sender, EventArgs e)
{
ReleaseCaller("PANIC PANIC PANIC");
}
private void ReleaseCaller(string result)
{
lock (Sync)
{
_theSomething = result;
Monitor.Pulse(Sync);
}
}

}
public void MethodA()
{
MethodAState state = new MethodAState();
string value = state.StartAndWaitMethodB();
Console.WriteLine(value);
}
}
class ClassB
{
public event EventHandler SomethingHappened, SomethingElseHappened;
private string _theSomething;
public string TheSomething { get { return _theSomething; } }
private void OnEvent(EventHandler handler)
{
if (handler != null) handler(this, EventArgs.Empty);
}
public void MethodB()
{
string value = Console.ReadLine();
if (value == "boom")
{
OnEvent(SomethingElseHappened);
}
else
{
_theSomething = value;
OnEvent(SomethingHappened);
}
}
}

Thanks Marc :)

This example looks very interesting, I will try to apply the idea to my
code as soon as I get a free moment from other stuff.

/Aidal
By the way, do the internal MethodState class have to be internal or
could it just as well be a public class next to ClassA and ClassB ?

/Aidal
Feb 1 '07 #12
It perfectly well could be, but the only reason for its existance is
to manage the state during a threaded method invoke. There is no
reason for this to be public, as nothing outside should care about it;
equally, this is one of the (rare) cases where (IMO) a nested class
helps to clarify the class scope. If multiple methods in the same
assembly have similar scope requirements then I guess I might elevate
it to a namespace-level class, and *perhaps* make it public if it is
common across assemblies. But nested and internal was my instinct for
this.

Marc
Feb 1 '07 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

77
by: Jon Skeet [C# MVP] | last post by:
Please excuse the cross-post - I'm pretty sure I've had interest in the article on all the groups this is posted to. I've finally managed to finish my article on multi-threading - at least for...
4
by: Bardo | last post by:
Hi, I have a situation where I am capturing both a WMI event utilising the "ManagementEventWatcher" in the "System.Management" namespace, and a corresponding event ("EntryWritten") raised from...
6
by: MPH Computers | last post by:
Hi I am looking for some help on Threading and Critical Sections I have a main thread that controls an event the event handler creates a new thread for carrying out the work because the...
5
by: Andrew Lippitt | last post by:
What gaurantees are there in the way of which thread the events are called from. I've seen: Thread A Begin Thread B Begin Thread A End Thread A End That seems to indicate that Begin and End...
2
by: elziko | last post by:
I have an object (Object1) that instantiates another class (Object2) in a seperate thread. It must be in its own thread for an ActiveX control it hosts to work. From Object1 I can get to all the...
0
by: BenLeino | last post by:
Hi out there, I have a little problem with threading an event receiving. I have a custom Class (DLL) that raises Events. When I run the Instance without threading it works fine. When I do...
13
by: Bob | last post by:
My WinForms app runs on the single default thread, and uses a single SqlConnection object for all queries. I need to use one or more timers to periodically execute some of them. My own testing...
5
by: Spam Catcher | last post by:
Hi all When .NET fires and event, does the event handler execute under a new thread, or does it execute under the primary application thread? Basically if I have events firing, do the event...
5
by: JasonX | last post by:
Im having problems with my program, in that if I close the main form while my new thread is doing work which involves writing to the main form, then I get an error about a disposed object. To...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.