你好我有一个有很多后台工作者的程序。那些后台工作人员什么都不做,只是听一个名为“tweet”的变量,然后每个后台程序为每个“推文”创建一个任务来处理它并准备好处理另一个推文。
以下是Tweet类,每1秒或更短时间更新一次。
Tweet tweet = new Tweet();
public class Tweet : INotifyPropertyChanged
{
private ITweet lastTweet;
protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, e);
}
protected void OnPropertyChanged(string propertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
public ITweet LastTweet
{
get { return lastTweet; }
set
{
if (value != lastTweet)
{
lastTweet = value;
OnPropertyChanged("LastTweet");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
现在在我的BackgroundWorker DoWork实施中:
Del OnNewTweetEvent = delegate(object sender2, PropertyChangedEventArgs args)
{
Task task = null;
task = new Task(() =>
{
var mytweet = sender2 as Tweet;
var tweetText = mytweet.LastTweet.Text;
//copy the tweetText in case the mytweet variable changed ( not sure )
ProcessTweet( tweetText );
});
task.Start();
};
this.tweet.PropertyChanged += new PropertyChangedEventHandler(OnNewTweetEvent);
//wait and prepare for cancellation
var backgroundworker = sender as BackgroundWorker;
while (true)
{
Thread.Sleep(10);
if (backgroundworker.CancellationPending)
{
//remove the notification
this.tweet.PropertyChanged -= new PropertyChangedEventHandler(OnNewTweetEvent);
return;
}
}
}
这个代码逻辑是对的吗?如果推文每隔0.01秒发送一次推文,我能将它们全部拿出来怎么办?或者推特可能会在没有我的后台工作人员的情况下改变它?
有队列或其他东西更好吗? 感谢您的帮助。
答案 0 :(得分:0)
正如您已经怀疑的那样,您的示例中的方法可能无法捕获每条推文或保证每条推文仅处理一次。因此,您应该将它们存储在一个集合中。队列非常适合此目的。
更直接的方法是让一个后台任务监视队列并启动一个异步任务来处理队列中的新推文。
但是,有人需要将推文放入队列中(或者在示例中更新Tweet对象的属性)。因此,最简单和最好的方法是在新推文到达时立即启动异步任务。这消除了等待新推文的后台任务,并删除了系统可能中断的位置。
根据您的代码示例,以下代码显示了一个简单的方法来处理新推文到达时。您可能希望将代码移动到代码中的另一个位置,并根据需要重命名类型。根据您的评论,此示例还针对不同的推文类型采取不同的操作:
// No need to implement INotifyPropertyChanged as there is no listener anymore
public class Tweet
{
private ITweet lastTweet;
public ITweet LastTweet
{
get { return lastTweet; }
set
{
if (value != lastTweet)
{
lastTweet = value;
var actionForTweet = GetActionForTweet(lastTweet);
Task task = new Task(() =>
{
actionForTweet(lastTweet);
});
task.Start();
}
}
}
private static Action<ITweet> GetActionForTweet(ITweet tweet)
{
// Decide what to do for which kind of tweet
// In the simplest case this is an if/switch statement
if ( ... )
return x => {
var tweetText = x.Text;
ProcessTweet( tweetText );
};
else
return x => {
// Do something else
};
}
}