Threading, Winforms, separating TCP operations from the main window form
In my main window form, I have some TCP/IP stuff going开发者_如何学C on. I'm currently refactoring so everything is in separate classes. I have these functions separated out (TCP now handled by a class called Communicator), but I just noticed that
this.Invoke(PDDelegate, new Object[] { tempstr });
this part depends on some infrastructure in the Form class. This is what sets up the delegate for processing data that arrives over the TCP pipe.
I'm tempted to pass in a reference to the main window when I call Communicator.Connect, so I could do
window.Invoke(PDDelegate, new Object[] { tempstr });
But that just seems like a hack to me. I'm wondering if I should worry about this and figure out how to give this object the ability to handle its own threads, or just pass in the pointer.
Perhaps a better way is to embrace the .NET event model. Have the Communicator
class implement an event and have the form subscribe to that event. That way, you have a clear separation of duties.
In communicator:
public delegate void CommEventHandler(object sender, CommEventArgs e);
public event CommEventHandler CommEvent;
And then the Communicator raises CommEvent whenever appropriate.
In the form, create the communicator and subscribe to the event:
private Communicator Comm = new Communicator();
Comm.CommEvent += MyCommEventHandler;
The form should then call Invoke
as required if it needs to update the UI.
That model eliminates the need for the Communicator to know anything about Forms.
Yup, that's a hack, all right.
For socket communication, I recommend a SynchronizationContext
-based approach. e.g., the Nito.Async.Sockets library uses SynchronizationContext
to marshal results back to the UI thread, without creating a dependency on Windows Forms.
Alternatively, you could write your own wrappers based on Rx. I think that would be a fine idea, but more complex.
精彩评论