Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8545293
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 11, 20262026-06-11T12:45:35+00:00 2026-06-11T12:45:35+00:00

I have code like this in a method: ISubject<Message> messages = new ReplaySubject<Message>(messageTimeout); public

  • 0

I have code like this in a method:

ISubject<Message> messages = new ReplaySubject<Message>(messageTimeout);

public void HandleNext(string clientId, Action<object> callback)
{
    messages.Where(message => !message.IsHandledBy(clientId))
            .Take(1)
            .Subscribe(message =>
                       {
                           callback(message.Message);
                           message.MarkAsHandledBy(clientId);
                       });
}

What is the rx’y way to code it, so that no race between MarkAsHandledBy() and IsHandledBy() may happen on multiple concurrent calls to HandleNext()?

EDIT:

This is for long polling. HandleNext() is called for each web request. The request can only handle one message and then returns to the client. Next request takes the next message and so forth.

The full code (still a work in progress of course) is this:

public class Queue
{
    readonly ISubject<MessageWrapper> messages;

    public Queue() : this(TimeSpan.FromSeconds(30)) {}

    public Queue(TimeSpan messageTimeout)
    {
        messages = new ReplaySubject<MessageWrapper>(messageTimeout);
    }

    public void Send(string channel, object message)
    {
        messages.OnNext(new MessageWrapper(new List<string> {channel}, message));
    }

    public void ReceiveNext(string clientId, string channel, Action<object> callback)
    {
        messages
            .Where(message => message.Channels.Contains(channel) && !message.IsReceivedBy(clientId))
            .Take(1)
            .Subscribe(message =>
                       {
                           callback(message.Message);
                           message.MarkAsReceivedFor(clientId);
                       });
    }

    class MessageWrapper
    {
        readonly List<string> receivers;

        public MessageWrapper(List<string> channels, object message)
        {
            receivers = new List<string>();
            Channels = channels;
            Message = message;
        }

        public List<string> Channels { get; private set; }
        public object Message { get; private set; }

        public void MarkAsReceivedFor(string clientId)
        {
            receivers.Add(clientId);
        }

        public bool IsReceivedBy(string clientId)
        {
            return receivers.Contains(clientId);
        }
    }
}

EDIT 2:

Right now my code looks like this:

public void ReceiveNext(string clientId, string channel, Action<object> callback)
{
    var subscription = Disposable.Empty;
    subscription = messages
        .Where(message => message.Channels.Contains(channel))
        .Subscribe(message =>
                   {
                       if (message.TryDispatchTo(clientId, callback))
                           subscription.Dispose();
                   });
}

class MessageWrapper
{
    readonly object message;
    readonly List<string> receivers;

    public MessageWrapper(List<string> channels, object message)
    {
        this.message = message;
        receivers = new List<string>();
        Channels = channels;
    }

    public List<string> Channels { get; private set; }

    public bool TryDispatchTo(string clientId, Action<object> handler)
    {
        lock (receivers)
        {
            if (IsReceivedBy(clientId)) return false;
            handler(message);
            MarkAsReceivedFor(clientId);
            return true;
        }
    }

    void MarkAsReceivedFor(string clientId)
    {
        receivers.Add(clientId);
    }

    bool IsReceivedBy(string clientId)
    {
        return receivers.Contains(clientId);
    }
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-11T12:45:36+00:00Added an answer on June 11, 2026 at 12:45 pm

    It seems to me that you’re making an Rx nightmare for yourself. Rx should provide a very easy way to wire up subscribers to your messages.

    I like the fact that you’ve got a self contained class holding your ReplaySubject – that stops somewhere else in your code being malicious and calling OnCompleted prematurely.

    However, the ReceiveNext method doesn’t provide any way for you to remove subscribers. It is a memory leak at least. You tracking of client ids in the MessageWrapper is also a potential memory leak.

    I’d suggest you try to work with this kind of function rather thanReceiveNext:

    public IDisposable RegisterChannel(string channel, Action<object> callback)
    {
        return messages
            .Where(message => message.Channels.Contains(channel))
            .Subscribe(message => callback(message.Message));
    }
    

    It’s very Rx-ish. It’s a nice pure query and you can unsubscribe easily.

    Since the Action<object> callback is no doubt directly related to the clientId I’d think about putting the logic to prevent duplicate message processing in there.

    Right now you code is very procedural and not suited to Rx. It seems like you haven’t quite got your head around how to best work with Rx. It’s a good start, but you need to think more functionally (as in functional programming).


    If you must use your code as-is, I’d suggest some changes.

    In Queue do this:

    public IDisposable ReceiveNext(
        string clientId, string channel, Action<object> callback)
    {
        return
            messages
                .Where(message => message.Channels.Contains(channel))
                .Take(1)
                .Subscribe(message =>
                    message.TryReceive(clientId, callback));
    }
    

    And in MessageWrapper get rid of MarkAsReceivedFor & IsReceivedBy and do this instead:

        public bool TryReceive(string clientId, Action<object> callback)
        {
            lock (receivers)
            {
                if (!receivers.Contains(clientId))
                {
                    callback(this.Message);
                    receivers.Add(clientId);
                    return true;
                }
                else
                    return false;
            }
        }
    

    I really don’t see why you have the .Take(1) though, but these changes may reduce the race condition depending on its cause.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have code like this @Override public void onCreate(Bundle savedInstanceState) { addItemsOnSpinnerOrgaLevel(); btn_getReport.setOnClickListener(new OnClickListener()
I have code like this: string uriString = @C:\Temp\test.html; Uri uri = new Uri(uriString);
i have code like this public class People { public string name { get;
i have a code like this i have defined the method goNext but still
I have code like this: ... entry.KeyPressEvent += EntryKeyPressEvent; ... } void EntryKeyPressEvent(object o,
I have code like this: MediaElement me = myPlayer.MediaElement; WriteableBitmap wb = new WriteableBitmap(me.NaturalVideoWidth,
I typically have code like this on a form: private void PerformLongRunningOperation() { BackgroundWorker
If I have a piece of code that looks like this: - (void)testSomething {
I have an camera Activity like this: public void startCamera() { Log.d(ANDRO_CAMERA, Starting camera
I have code like this: public form() { InitializeComponent(); init(); //read ini and try

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.