简体   繁体   中英

Using Rx for a long running task in WebForms

I've just read the entirety of this article and I'm struggling with the code, trying to implement a long running task in a WebForms page and using Rx to retrieve the values. I'm starting to think it is kind of impossible, but figured it would be constructive to ask this anyways since there is very limited info on Rx, much less Rx alongside WebForms (haven't found a single post/article that referred to both).

What I would like to achieve is fairly simple actually. I have a method that reads data from a csv file and does a bunch of processing on it. Currently, it populates two lists, one with "success messages" and the other with "error messages". The current design is admittedly quite bad, but bear with me on this one...

These two lists are then bound to two different gridviews in the aspx.

The problem here is that the task takes quite a while to complete, and we didn't want to make the user wait a long time without any feedback.

The current implementation is very lousy in my opinion, but works:

  1. The user selects the .csv file though a FileUpload control
  2. A button is clicked on the page to initiate the process
  3. Two lists are then created and stored in session keys
  4. A background thread is created and receives the long running void method, which in turn receives both lists and adds new messages to them on every iteration. The thread itself is also stored in a separate session variable
  5. A timer is enabled on the page, and the interval is set to 1000 (one second)
  6. When the timer ticks, the gridviews are databound with the lists, updating the interface
  7. On Page_Load, the thread variable is checked to see if it is still alive, and if not, the timer is disabled.

Is there a way to make this work using Rx without session variables somehow? I thought it would be possible to use the .Scan method to assemble the whole history of messages (this is why I asked this ), making the click the trigger to start everything and the tick the trigger to actually receive the messages. The subscription code would then be a simple bind of the results to the gridviews. Since datasources in WebForms do not retain old values, this is needed to refresh everything at every tick.

I could actually compose most of this, but when the delegates fired to bind the grid, nothing happened because that was all happening on other threads. I can't see a way to control all this seeing as every request to the webapplication is started on an unknown thread. Is there a way to simulate the user interaction that happens on a WPF or WinForms application in this context to make this work?

I'll take a crack at answering. The main difference between IEnumerable and IObservable is pull vs push. That is, IEnumerable only returns the next value when one is requested, whereas IObservable pushes the next value out immediately via .OnNext() . This suggests that IObservable is not compatible with a polling client, which is fundamentally pull based.

To me, the only way RX would make sense in the scenario would be to use use websockets, which enables push-based communication from the server. ( SignalR is a good "official" websockets integration for ASP.Net.) This would allow you to connect the server data source as a subscriber to the background thread's IObservable. The observer thread would receive new events immediately, and could then immediately push them to the client for display.

I understand that this approach would require a substantial re-factor. I just don't see the point in switching to an RX observable source, in a case where the consumer is just doing a full-refresh poll.

Sorry about the lack of Web stuff in the article/book. I have been working almost solely with WPF/Silverlight for UI for the last few years. Just recently I have started a project that is a Web project and I too have a long running query that trickles data back to the user, and it sure is a lot harder than WinForm/WPF/Silverlight to do.

I am going down the SignalR path, but even that seems to have some friction with Rx. The main problem I have faced is that Rx doens't block so the SignalR method I call completes very quickly and then the connection gets severed. If I can figure out how to do it well, I will post the pattern to use here.

But just so you know you are not alone....

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM