1

i'm trying to figure with the best method to deal multiple class to a method that use a blocking resource.

The goal:

permit the multiple calls to a method that use a DataReader. While this first call is in progress, Keeping the rest to calls (if present) on hold until the method ends.

When the this method finish it's execution, i need to discard every request accumuled while the first execution was in progress, only permitting that the last request execute.

In specific i'm dealing with repeated event firing in a Windows.Forms object that call a DataReader that doesn't finish to execute and the next call that comes behind it raises an exception.

Any ideas to design this part ?

Rafael
  • 3,081
  • 6
  • 32
  • 53
  • Can you rephrase your question? It's hard to understand what's you real problem. I suspect that you're trying to create someting like a connection pool and you can use a connection at once? Or what? ... – Matías Fidemraizer Oct 31 '12 at 20:01
  • @MatíasFidemraizer ok edited my question i hope that i have explained well this time – Rafael Oct 31 '12 at 20:09
  • Regarding `only permitting that the last request execute`, do you mean that if several requests are received while on execution is in progress then all but the last received request should be discarded but that last one -- also received while the first was being processed -- is processed? Let us say `R1` is received and while it is being processed `R2`, `R3` and `R4` are received in that order. Should `R4` be processed? – Miserable Variable Oct 31 '12 at 20:15
  • @MiserableVariable yeah that's rigth, but only when R1 finish – Rafael Oct 31 '12 at 20:18

4 Answers4

3

So you have an event handler, and it's triggered repeatedly over time. You want it to just do nothing if a previously fired handler is still running. That's simple enough, just add a boolean "isRunning" as an instance field, and if it's true do nothing. Just be careful to synchronize access to the variable properly:

private int isRunning = 0;//there is no bool overload for `Interlocked.Exchange`
private void button1_Click(object sender, EventArgs e)
{
    if (Interlocked.Exchange(ref isRunning, 1) == 0)
    {
        //do stuff

        isRunning = 0;
    }
    else
    {
        //another handler is already in progress; 
        //possibly display message to user, or do nothing, or whatever
    }
}

If you don't want subsequent event handlers to be skipped, but you instead just want them to wait and ensure that only one is performing the query at a time then you can just use lock:

private object key = new object();
private void button1_Click(object sender, EventArgs e)
{
    lock (key)
    {
        //do stuff
    }
}
Servy
  • 202,030
  • 26
  • 332
  • 449
  • while i didn't choose your answer as the correct one i will award you with 50 rep (when it's available) for your answer, due to the fact you show me how to implemente the lock feature, and it's a good one – Rafael Oct 31 '12 at 22:07
  • a promise is a debt. greetings – Rafael Nov 26 '12 at 15:04
0

In Java, you'd mark the method synchronized and all would be well.

In C#, you need to do some more work. See this question for some options. The accepted answer doesn't look like the best one to me; try using the lock keyword first.

Community
  • 1
  • 1
Thomas
  • 174,939
  • 50
  • 355
  • 478
  • 2
    this will ensure that only one runs at a time; it won't cause subsequent fires to be skipped. It's a bit unclear which is desirable from the question. – Servy Oct 31 '12 at 20:06
  • Oh, you're right. Leaving this here because `lock` might still be useful, but more work is needed. – Thomas Oct 31 '12 at 20:09
0

If request R1 is received and while it is being processed R2, R3 and R4 are received in that order then R2 and R3 should be discarded and R4 should be processed after R processing is finished.

The pseudo-code is something like the following:

receive request thread

if current_request is null
    assign to current_request
else
    assign to next_request

process request thread:

while true
    if current_request is not null
        process it
        set current_request = next_request, next_request = null

Changes to next_request and current_request should be done using the same lock.

Miserable Variable
  • 28,432
  • 15
  • 72
  • 133
0

This is best done with Reactive Extension, just use Throttle the event trigger

Rohit Sharma
  • 6,136
  • 3
  • 28
  • 47