Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Okay, so I tried to create a Fast A and AB and then a slow B. This means that my overall time is slower (mainly because of the b-only stream), but the combined time and a-only time is faster. Here are the results:</p> <pre><code>A's only: 00:00:00.3975499 Combine: 00:00:00.4234934 B's only: 00:00:02.0079422 Total: 00:00:02.8314751 0: 0 A: 700 B: 200 AB: 100 Generated A: 800, Sent A: 800 Generated B: 300, Sent B: 300 </code></pre> <p>Here's the code:</p> <pre><code> class MessageWrapper { object bMessageLock = new object(); object pendingBLock = new object(); int? pendingB; ManualResetEvent gateOpen = new ManualResetEvent(true); // Gate is open initially. private bool IsGateOpen() { return gateOpen.WaitOne(0); } private void OpenGate() { gateOpen.Set(); } private void CloseGate() { gateOpen.Reset(); } public Message WrapA(int a, int millisecondsTimeout) { // check if the gate is open. Use WaitOne(0) to return immediately. if (IsGateOpen()) { return new Message(a, null); } else { // This extra lock is to make sure that we don't get stale b's. lock (pendingBLock) { // and reopen the gate. OpenGate(); // there is a waiting b // Send combined message var message = new Message(a, pendingB); pendingB = null; return message; } } } public Message WrapB(int b, int millisecondsTimeout) { // Remove this if you don't have overlapping B's var timespentInLock = Stopwatch.StartNew(); lock (bMessageLock) // Only one B message can be sent at a time.... may need to fix this. { pendingB = b; // Close gate CloseGate(); // Wait for the gate to be opened again (meaning that the message has been sent) if (timespentInLock.ElapsedMilliseconds &lt; millisecondsTimeout &amp;&amp; gateOpen.WaitOne(millisecondsTimeout - (int)timespentInLock.ElapsedMilliseconds)) // If you don't have overlapping b's use this clause instead. //if (gateOpen.WaitOne(millisecondsTimeout)) { lock (pendingBLock) { // Gate was opened, so combined message was sent. return null; } } else { // Timeout expired, so send b-only message. lock (pendingBLock) { // reopen gate. OpenGate(); pendingB = null; return new Message(null, b); } } } } } </code></pre> <p>The main work is done my using a manual reset event. The idea is that if the gate is open, then you can send A's freely. When a 'b' arrives, you close the gate and force A to combine it. I must say that having a single <code>pendingB</code> field restricts this operation somewhat. Having only one variable means that only one thread can store it's b in pendingB. This is why I have the extra <code>bMessageLock</code>. </p> <p>Also, access to this variable needs to be controlled, hence the <code>pendingBLock</code>.</p> <p>There may still be bugs in this code, but as much as I test it, I still get all 100 messages combined.</p> <p>Lastly, I included the check against the time that WrapB was waiting. Originally the WrapB's would just queue up taking a total of 200 seconds. If you have overlapping calls, then you can add the check. If you don't mind them queuing up, use the simpler code instead.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload