c#:使用相同变量的多个事件的单个处理程序:最佳实践
本文关键字:处理 单个 程序 最佳 事件 变量 | 更新日期: 2023-09-27 17:51:12
考虑下一个代码。这是一个临时的一次性解决方案(跳过了很多逻辑,代码本身也简化了),但是在我编写它的时候,我想到了一些问题。
它从uri中检索文件,如果从文件夹'j'检索时出现错误,它将停止从该文件夹中进一步检索。
据我所知,这段代码是不是线程安全?虽然它看起来对我来说很好,但出于好奇心和自我教育(因为我几乎没有多线程的经验),我想一劳永逸地弄清楚:
- 是
openedConnections
和failed
(实际上也存在Remove
)变量受到数据竞赛或其他东西的威胁吗? - 如果它不是线程安全的,使它安全的最佳实践是什么?在哪里添加
lock
s等等? - 如果这些变量不存在,是否存在任何类型的不一致?我的意思是,它是好添加
DownloadDataCompleted
处理程序到几个事件? 将
DownloadDataCompleted
作为专用类的非静态成员并编写webClient.DownloadDataCompleted += new Dedicated().DownloadDataCompleted;
是否有一些好处?总的来说,你的观点是:解决这类任务的最好方法是什么?不考虑小的代码优化,但概念(或者我必须写"概念"?o_O) public class SomeClass
{
static HashSet<int> failed = new HashSet<int>();
static int openedConnections = 0;
static void DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
openedConnections--;
if (e.Error != null)
{
failed.Add(MyToken(e.UserState).j);
return;
}
//save data
}
public void Retrieve()
{
for (int i = 1; i < 10000; i++)
for (int j = 1; j < 10000; j++)
{
if(failed.Contains(j)) continue;
WebClient webClient = new WebClient();
webClient.DownloadDataCompleted += DownloadDataCompleted;
var uri = string.Format("someuri/{1}/{0}", i, j);
webClient.DownloadDataAsync(new Uri(uri+".jpg"), /*token here*/);
openedConnestions++;
while (openedConnections > 32)Thread.Sleep(111);
}
}
}
- 当然。
lock()
每次访问前的列表本身(Add
和Remove
)。 我不太明白你的问题。是否可以对不同的事件有相同的处理程序?当然,谁在乎呢,这只是代码而已。这个特定的处理器是好的吗?实际上不是,整个体系结构也不是,直到TCP级别。这不是Windows设计用来处理TCP连接的方式
如果你按代码行支付报酬,当然。企业应用程序就是这样编写的。
如果按浪费的内存或CPU周期付费就更好了。从概念上讲,编写web爬虫的传统方法是生成一些线程(这个数量由您的系统定义,它可以处理多少连接),将下载URL推送到数组中(不要忘记
lock
),并在处理程序中从数组中弹出一个URL(再次不要忘记lock
)并同步下载它。当物品用完时,只需返回即可(或者如果您正在动态添加物品,请等待,直到获得更多物品)。