我为此奋战了好几天,希望你能把我推向正确的方向。C#通过状态对象来改变任务
这是一个递归线程算法,它解析线程中的资源,寻找指向将来TakeOut的ConcurrentBag
中的其他资源的链接。线程创建受限于具有可配置大小的数组以保留资源。
我有一个private static ConcurrentBag<string>
它被许多线程填充。这些是Tasks
,它们存储在private static Task[]
中,具有可配置的大小(应用程序首选项)。
在Main
中有一个循环,它在做TryTake()
变成本地string url
变量。全成当它循环的Task[]
试图找到空插槽,创造新Task
穿过状态对象url
并将其存储在Task[]
这样的:
TaskArray[x] = new Task(FindLinks, url, TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
的FindLinks
声明为
private static readonly Action<object> FindLinks = input => { ... }
在主Task[]
循环我将url
设置为null
,然后再下一个TryTake(out url)
。
这里我的问题是什么,在主循环中从url
传递的状态对象input
变成null
里面的任务lambda函数。我读过几乎快要TPL所有MSDN文章,我如何传递一个变量(字符串)Task
安然无封(或不管它是发生)想不通这一个:(
。
关于改善这个算法任何其他的想法也欢迎
感谢
编辑:。
我已经重新排序报表和轻微重写代码在主回路的问题解决了没有更多的分配空的我怀疑它是由...造成的编译器的语句重新排序或抢占。这里是什么样子,现在没有造成更多的麻烦:
string url;
if (CollectedLinks.TryTake(out url))
{
var queued = false;
while (!queued)
{
// Loops thru the array looking for empty slot (null)
for (byte i = 0; i < TaskArray.Length; i++)
{
if (TaskArray[i] == null)
{
TaskArray[i] = new Task(FindLinks, url, TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness);
TaskArray[i].Start(TaskScheduler.Current);
queued = true; break;
}
}
if (!queued)
{
// Loop and clean the array
for (var i = 0; i < TaskArray.Length; i++)
{
if (TaskArray[i] == null)
continue;
if (TaskArray[i].Status == TaskStatus.RanToCompletion || TaskArray[i].Status == TaskStatus.Canceled || TaskArray[i].Status == TaskStatus.Faulted)
{
TaskArray[i].Wait(0);
TaskArray[i] = null;
}
}
}
}
}
你*描述*大量的代码,但是这将是一个更加清晰,如果你能真正*显示*代码。很难跟踪正在发生的事情。特别是,答案很容易取决于你是否捕获任何变量。 – 2011-04-15 07:31:35
我明白了。不幸的是,代码非常复杂和重构,以至于我需要一些时间才能收集所有必要的数据并过滤掉其余的数据,并且可能需要您在同一时间将它们连接在一起。不过,我会尽我所能。 – Slavius 2011-04-15 15:29:06
如果您已经解决了问题(因为看起来有问题),则应该将解决方案作为答案发布,并将其标记为已回答。这会让其他人更快地知道问题已经解决。 – Yetti 2011-04-20 15:45:15