C#线程同步问题

发布于 2024-12-03 02:36:50 字数 887 浏览 1 评论 0原文

所以我看到了使用线程进行有趣的事情。

我有一个启动 2 个线程并继续其生命的方法,我尝试执行以下操作以确保安全。

    bool CopyOk1 = false;
    bool CopyOk2 = false;
    new Thread(() => FirstMethod(tempList1, ref CopyOk1)).Start();
    new Thread(() => SecondMethod(tempList2, ref CopyOk2)).Start();
    var spinner = new SpinWait();
    while (!CopyOk1 || !CopyOk2)
        spinner.SpinOnce();

然后在这两种方法中我都从以下内容开始

    private static void FirstMethod(List<T> templist, ref bool CopyOk)
    {
        var temp = new T[templist.Count];
        templist.CopyTo(temp);
        CopyOk = true;
        //moves on
    }

我的目的是复制传递的列表,以便我可以尽快在线程内安全地更改和使用它以解锁调用者线程。

我的问题是,在第二种方法中,在数组初始化和列表 CopyTo 之间,基本列表会以某种方式发生变化。

这些列表是在调用者线程内创建的,并且在线程启动后并未实际使用,因此我完全不知道这是如何/为什么发生的。

毫无疑问,我在这里做错了什么,但我的菜鸟技能不会让我看到,任何帮助都是值得赞赏的。

So I'm seeing fun stuff playing with threads.

I have a method that starts 2 threads and goes on with its life and I tried doing the following to keep things safe.

    bool CopyOk1 = false;
    bool CopyOk2 = false;
    new Thread(() => FirstMethod(tempList1, ref CopyOk1)).Start();
    new Thread(() => SecondMethod(tempList2, ref CopyOk2)).Start();
    var spinner = new SpinWait();
    while (!CopyOk1 || !CopyOk2)
        spinner.SpinOnce();

then in both methods I start with the following

    private static void FirstMethod(List<T> templist, ref bool CopyOk)
    {
        var temp = new T[templist.Count];
        templist.CopyTo(temp);
        CopyOk = true;
        //moves on
    }

My intention here is to copy the passed list so I can change and use it safely inside the threads ASAP to unblock the caller thread.

My problem is that on the second method unpredictably, between the array initialization and the list CopyTo the base list changes, somehow, by something.

These lists are created inside the caller thread and are not actually used after the threads are started so I have absolutely NO idea how/why this is happening.

No doubt I'm doing something wrong here, but my noobish skills won't let me see, any help is appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

深海里的那抹蓝 2024-12-10 02:36:50

使用全局锁而不是锁定“templist”。然后使用同一锁保护所有修改源列表的代码。

另外,也许旁白,但等待线程部分完成可以更优雅地完成,即不涉及循环。使用 ManualResetEvent 将允许您的原始线程等待其他线程中发生“某些事情”。使用 WaitOne 将阻塞线程,直到在另一个线程中调用 Set()。

private object m_Lock = new object();
private ManualResetEvent m_ResetOne = new ManualResetEvent(false);
private ManualResetEvent m_ResetTwo = new ManualResetEvent(false);

(...)

new Thread(() => FirstMethod(tempList1)).Start();
new Thread(() => SecondMethod(tempList2)).Start();
m_ResetOne.WaitOne();
m_ResetTwo.WaitOne();

(...)

private void FirstMethod(List<T> templist)
{
    lock (m_Lock)
    {
        var temp = new T[templist.Count];
        templist.CopyTo(temp);
    }
    m_ResetOne .Set();
    //moves on
}

Instead of locking 'templist', use a global lock. Then protect all code that modifies the source list with that same lock.

Also, perhaps an aside, but waiting for a thread to partially complete can be done more elegantly, i.e not involving a loop. Using a ManualResetEvent will allow your original thread to wait for 'something' to occur in other threads. Using WaitOne will block the thread until a Set() is called in the other thread.

private object m_Lock = new object();
private ManualResetEvent m_ResetOne = new ManualResetEvent(false);
private ManualResetEvent m_ResetTwo = new ManualResetEvent(false);

(...)

new Thread(() => FirstMethod(tempList1)).Start();
new Thread(() => SecondMethod(tempList2)).Start();
m_ResetOne.WaitOne();
m_ResetTwo.WaitOne();

(...)

private void FirstMethod(List<T> templist)
{
    lock (m_Lock)
    {
        var temp = new T[templist.Count];
        templist.CopyTo(temp);
    }
    m_ResetOne .Set();
    //moves on
}
帝王念 2024-12-10 02:36:50

您发布的代码中没有任何内容表明您做错了什么。问题必须出在其他地方——正如评论者所建议的,最有可能的是在填充 List1/List2 的代码中。如果您也在线程化它,也许您不会等待该线程完成填充列表然后再继续?

Nothing in the code that you posted suggests that you are doing anything wrong. The problem has to lie elsewhere- most likely, as commenters have suggested, in the code that populates List1/List2. If you are threading that as well, perhaps you are not waiting for that thread to finish populating the lists before proceeding?

猫瑾少女 2024-12-10 02:36:50

尝试这个并检查行为

private static void FirstMethod(List<T> templist, ref bool CopyOk)
{
    T[] temp;

    lock (templist)
    {
        temp = new T[templist.Count];
        templist.CopyTo(temp);
    }
    CopyOk = true;
    //moves on
}

Try this and check the behavior

private static void FirstMethod(List<T> templist, ref bool CopyOk)
{
    T[] temp;

    lock (templist)
    {
        temp = new T[templist.Count];
        templist.CopyTo(temp);
    }
    CopyOk = true;
    //moves on
}
寒尘 2024-12-10 02:36:50

您需要某种类型的同步机制来防止 List 被更改。我们在当前示例中看不到足够的代码来保证它没有被更改。

You need some type of synchronization mechanism to prevent List<T> from being changed. We can't see enough code in the current sample to warrant that it is not being altered.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文