Turning an Event into a Task [Answered]
I have a method that needs to send a message over the network, and then wait for a response before returning something. Due to some quirks, the only way to get a response is via an event. What is an appropriate way to have the method wait for the event, and get the data from it?
I have tried setting up a TaskCompletionSource in a private field, that the method awaits, and the event sets the result - but the event could trigger from code I didn't write, and basically could end up returning the wrong data. And having to use a private field feels bad, though I don't know what alternatives I have
I have tried setting up a TaskCompletionSource in a private field, that the method awaits, and the event sets the result - but the event could trigger from code I didn't write, and basically could end up returning the wrong data. And having to use a private field feels bad, though I don't know what alternatives I have
31 Replies
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
That example is good, yeah, thanks - though, I make a request that triggers incoming data, then need to wait for it. That is sort of what I have - but the problem is if say, another thread triggers some non-null incoming data after I trigger data, so that I get data from that other thread instead of mine
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
but it's possible that another message was just finishing when I start listening again, and I get that message instead of the one I want
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
but data would be null in this situation; data is set to null because we're waiting for a message. We get a message, we set data. But it wasn't the message we're waiting for
I'm thinking, realistically, being threadsafe isn't possible unless I have something that can identify the message on both sides. And unless I use the full serialized content, I can't do that reliably because there's some code I can't touch
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Or maybe something clever with semaphores, I'm writing up an example, it's work code so I can't show real code
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
and yeah I have to assume. Though realistically in my situation, it's for tests and I happen to know that I've overridden the extension method for all my tests so all of them come through here
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
so in theory it's OK as-is, but I'd like to make it threadsafe
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
I have to assume it is
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
It's also possible (and even likely) that the event is fired synchronously as part of the send, but that feels like a flimsy implementation detail to rely on
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Right now my code looks most like this:
While in another method, when we get data about a messageId, we update CurrentMessageId
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
well, the thing I was pointing out with the code was that I don't have to wait for anything; when the Send is complete, my _currentMessageId is populated always. If it's synchronous, and in a lock, there is no chance that another message can trigger the event between them, right?
Because most code would do, as you did, just invoke the event - synchronously. And the lock is still in effect while that's happening
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Well. By synchronous I mean, it's a proper chain of awaits that should use only one thread max. But it's still async and awaiting. I'm not sure if that's really safe or just usually safe
Anyway, thanks, you're right - unless there is some implementation detail that makes the event synchronous from the time of send, I have to have an ID or something. And yeah, I think ideally I'd specify the ID from the send
Which would just require copying some ... pretty hefty code over from deep within the thing I don't want to modify, and bypassing most of the thing entirely. Which is not ideal, but... should work
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
Well basically I had a janky working version before, and was told that we'd need to get it approved and it would be shot down because it was janky. This is me trying to make it better
Using serialized json content as a key in a dictionary worked better tho, I didn't have thread problems 😛
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
right, but first, setting the response ID is the hard part. But that'll just be trying to cut through lots of 'helper' code obscuring the things I need
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
The Network package doesn't let me do that. At least not at surface level
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
As mentioned, I can grab some of its deep code and copy it to my code, and do it that way - but then I'm bypassing a lot of the package's code. So I'm unsure that's suitable, for a test, when the test may skip a lot of things
But anyway. I'll figure it out from here, thanks
✅ This post has been marked as answered!