1

嗨,我是使用并行任务的新手。我有一个需要并行运行多次的功能。下面是显示这一点的虚拟代码,

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) 这一行。请帮我解决这个问题。我认为全局变量有问题。

4

2 回答 2

3

你需要同步对共享数据的访问,因为每个线程会尝试同时访问它,并且看到它为空,然后将全部分配。

请注意,如果通过锁完成同步,则可能会导致三个线程有效地按顺序运行,因为一次只有一个线程可以进入锁。

于 2013-06-05T16:30:41.270 回答
1

好吧,为什么不做

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();
}
于 2013-06-05T16:46:32.877 回答