锁定线程以便在winforms中进行事务处理是一种好习惯吗?

时间:2011-12-06 16:04:51

标签: c# wpf winforms multithreading

这是我正在使用的旧学校winforms应用程序,他们使用的设计模式如下:

每当你需要事务处理时,就会在自己的线程上执行一个操作,并且线程被锁定(每个操作都使用一个特定的锁对象),然后调用wcf服务,一些是本地的更新对象,然后释放锁。

这是好习惯吗?

4 个答案:

答案 0 :(得分:1)

是的,但要小心多线程,并对其进行良好的阅读,因为太多的锁可能会造成死锁情况。

答案 1 :(得分:0)

我不太清楚你的意思,“锁定一个线程。”是这样的吗?

static object ThreadLock = new object();

void ThreadProc(object state)
{
    lock (ThreadLock)
    {
        // do stuff here
    }
}

如果是这样,那个设计没有什么问题。您的UI线程产生一个应该执行该代码的线程,并且该锁防止多个线程同时执行。这有点浪费,因为你可能有许多线程在锁定后面排队,但实际上你可能没有超过一个或两个线程在等待。有更有效的方法(实现某种任务队列),但你所拥有的是简单而有效的。

答案 2 :(得分:0)

只要您不等待多个锁定对象,这应该没问题。遇到这种情况时会发生死锁:

主题A:

lock (lockObject1)
{
    // Do some stuff

    lock (lockObject2)
    {
        // Do some stuff
    }
}

主题B:

lock (lockObject2)
{
    // Do some stuff

    lock (lockObject1)
    {
        // Do some stuff
    }
}

如果您碰巧在线程A中锁定了lockObject1,并且线程B在线程A锁定它之前锁定了lockObject2,那么两个线程都将等待另一个线程中锁定的对象,并且两者都不会解锁,因为每个线程都在等待一个物体被锁定。这是一个过于简单的例子 - 有很多方法可以在这种情况下结束。

为避免死锁,请勿在锁定第一个对象时等待第二个对象。如果你像这样一次锁定一个对象,你就不会死锁,因为最终,锁定线程会释放一个等待线程需要的对象。例如,上面应该展开:

主题A:

lock (lockObject1)
{
        // Do some stuff
}

lock (lockObject2)
{
        // Do some stuff
}

主题B:

lock (lockObject2)
{
        // Do some stuff
}

lock (lockObject1)
{
        // Do some stuff
}

在这种情况下,每次锁定操作都将完成,而不会尝试获取其他资源,因此可以避免死锁。

答案 3 :(得分:0)

这不会使行动成为交易。我认为这意味着整个操作成功或无效 - 如果我更新同步块中的两个本地对象,则第二个错误不会将更改回滚到第一个。

此外,没有什么能阻止主线程在更新时使用这两个对象 - 它还需要通过锁定来协作。

只有在主线程中使用这些对象时也锁定后台线程才有意义。