[嗨,我是使用并行任务的新手。我有一个函数,需要并行运行多次。下面是显示此代码的伪代码,
public MyClass GlobalValue;
static void Main(string[] args)
{
Task task1 = Task.Factory.StartNew(() => SaveValue());
Task task2 = Task.Factory.StartNew(() => SaveValue());
Task task3 = Task.Factory.StartNew(() => SaveValue());
}
public void SaveValue()
{
string val = GetValueFromDB();
if (GlobalValue == NULL)
{
GlobalValue = New MyClass(val);
}
else if (GlobalValue.Key != val)
{
GlobalValue = New MyClass(val);
}
string result = GlobalValue.GetData();
}
现在每次都会调用GlobalValue = New GlobalValue(val)行。请帮助我。我认为全局变量有问题。
嗯,为什么不这样做
static void Main()
{
var tasks = new[]
{
Task.Factory.StartNew(() => YourFunction()),
Task.Factory.StartNew(() => YourFunction()),
Task.Factory.StartNew(() => YourFunction())
};
Task.WaitAll(tasks)
}
public static string YourFunction()
{
var yourClass = new MyClass(GetValueFromDB());
return yourClass.GetData();
}
我不明白您为什么需要GlobalValue
。实例化MyClass
是否昂贵?更值得注意的是,您对结果不做任何事情,所以一切都没有意义。
由于功能可用,假设您使用的是.Net 4.5(c#5.0),则可以这样做
static void Main()
{
await Task.WhenAll(YourFunction(), YourFunction(), YourFunction());
}
public async Task<string> YourFunction()
{
return new MyClass(GetValueFromDB()).GetData();
}
为了说明,您仍然可以使用全局变量,但是它将大大减轻并行化的好处。您只需要确保序列化对共享状态的访问或使用为您执行此操作的线程安全类型。
根据您的示例改编,
private readonly SemaphoreSlim globalLock =
new SemaphoreSlim(1));
...
public void SaveValue()
{
string val = GetValueFromDB();
MyClass thisValue;
globalLock.Wait();
try
{
if (this.GlobalValue == NULL)
{
this.GlobalValue = new MyClass(val);
}
else if (this.GlobalValue.Key != val)
{
this.GlobalValue = new MyClass(val);
}
thisValue = this.GlobalValue
}
finally
{
globalLock.Release();
}
string result = thisValue.GetData();
}
您需要同步对共享数据的访问,因为每个线程将尝试同时访问它,并且看到它为空,然后所有线程都将分配。
请注意,如果通过锁完成同步,则可能会导致三个线程有效地顺序运行,因为一次只能有一个线程进入锁。