Reputation: 273
I create a thread for each of my network communications and they add to a list responses whenever they hear back from a client. I'm starting up the task below at execution to see if any communications come in. It displays the most recent one on screen.
Task task = new Task(
(() =>
{
int i = 0;
while (true)
{
if (responses.Count > i){
Debug.WriteLine(responses[i]);
int index = Form.ActiveForm.Controls.IndexOfKey("responseBox");
Form.ActiveForm.Invoke((MethodInvoker) (() => Form.ActiveForm.Controls[index].Visible = true));
Form.ActiveForm.Invoke((MethodInvoker) (() => Form.ActiveForm.Controls[index].Text = responses[i]));
i++;
}
}
}));
task.Start();
My question is; is there a better way for me to do this? It seems wrong to me to have the task constantly working for something that doesn't happen very often.
Edit: I'm very new to C#, so if there's something obvious please don't hesitate to point it out.
Update:
As per the nice tutorial from MS that sidewinder linked I added a simple event to the Add function of List. as So:
public delegate void ChangedEventHandler(object sender, EventArgs e);
public class listWithChanges<T> : List<T>
{
public event ChangedEventHandler Changed;
protected virtual void OnChanged(EventArgs e)
{
if (Changed != null)
Changed(this, e);
}
public new void Add (T item)
{
base.Add(item);
OnChanged(EventArgs.Empty);
}
}
and added to my output with a delegate
responses.Changed += ((o, e) => {
int index = Form.ActiveForm.Controls.IndexOfKey("responseBox");
Form.ActiveForm.Invoke((MethodInvoker) (() => Form.ActiveForm.Controls[index].Visible = true));
Form.ActiveForm.Invoke((MethodInvoker) (() => Form.ActiveForm.Controls[index].Text = responses[responses.Count - 1]));
});
Upvotes: 5
Views: 138
Reputation: 61969
If you don't want to have to go through great restructuring of your code, you can use a blocking queue for your responses
collection, so that your reading thread blocks while waiting for an item to appear in the queue.
Waiting for something to appear in a blocking queue consumes zero CPU. (Technically non-zero, but nonetheless unnoticeable.)
A quick search yields this: MSDN - BlockingCollection Class
Upvotes: 2
Reputation: 421
Events would be a nice solution.
An event is an implementation of the Observer pattern, in which the source (the network communications) warn it's observers(whoever calls the task in your example) that something happened.
It's a lot more efficient since it doesn't waste CPU usage in an infinite loop, the method only executes when a client responds.
C# has a great support for events, consider reading the MS Tutorial(originally posted by Sidewinder94).
Upvotes: 4