解决 跨线程问题控制

aaaron123

会员
已加入
2021年1月3日
留言内容
13
编程经验
1-3
C#:
 //The "while" below cause and exception:
        //System.InvalidOperationException:'Cross-thread operation not valid: Control lstFiles accessed from thread other than the thread it was created on.'
        private void watchFinished()
        {
            do
            {
                Thread.Sleep(50);
            }
            while (lstFiles.CheckedItems.Count != 0);

            showProgress(prgHole, 100);

            string ans = "Done";

            if (undeletable.Count != 0)
            {
                string[] items = new string[undeletable.Count];

                undeletable.CopyTo(items, 0);

                frmUndeletable frm = new frmUndeletable(items);

                frm.ShowDialog();
            }
            else
                ans += ", No Items TO Delete";


            MessageBox.Show(ans + " : " + prg.ToString() + " files deleted");
        }


请多多包涵,我不写C#,但是我有一个C#程序,它会产生上述错误。

我不需要学习C#,但是我确实需要该程序,如果您能告诉我如何修复它,将不胜感激。

如果我在上面没有提供足够的信息,也许您可​​以给我一些尝试。

无论如何,我将不胜感激。
 
Solution
我建议不要这样做,但是,如果您要这样做,则应采取以下步骤:

1.编写一种方法,该方法可以执行您想要的操作:
C#:
private bool AreAnyItemsChecked()
{
    return lstFiles.CheckedItems.Count != 0;
}
2. Add the use of InvokeRequired and Invoke:
C#:
private bool AreAnyItemsChecked()
{
    if (lstFiles.InvokeRequired)
    {
        // We are on a secondary thread so reinvoke the same method on the UI thread.
        return (bool)lstFiles.Invoke(new Func<bool>(AreAnyItemsChecked));
    }
    else
    {
        // We are on the UI thread so perform the desired action.
        return lstFiles.CheckedItems.Count != 0;
    }
}
3.打电话给...

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,501
地点
悉尼,澳大利亚
编程经验
10+
该错误消息表明您正在尝试从辅助线程上执行的代码访问UI。那是不可以的。首先,您正在尝试从控件中获取一些数据,这是直接的问题。即使没有这些,您仍将显示一个模式对话框和一个消息框,但是由于您在辅助线程上执行此操作,因此它们实际上都不会阻止用户访问调用表单。

You need top explain what you're actually trying to achieve in order for us the explain the correct way to achieve it. We shouldn't have to work it out from code that doesn't do it. If you want to perform an action when the user checks an item in a CheckedListBox then why aren't you handling the ItemCheck event of that control?
 

aaaron123

会员
已加入
2021年1月3日
留言内容
13
编程经验
1-3
感谢回复。

正如我所说的,我不是C#程序员,也不是我的代码。

我不认为我的请求属于该论坛的范围,但我希望有人希望提供帮助。

我认为 也许 知道错误消息并且涉及到交叉线程,有人会知道如何添加"如果(!lstFiles.InvokeRequired)"我在代码的其他地方看到过的那种语句。
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,501
地点
悉尼,澳大利亚
编程经验
10+
我建议不要这样做,但是,如果您要这样做,则应采取以下步骤:

1.编写一种方法,该方法可以执行您想要的操作:
C#:
private bool AreAnyItemsChecked()
{
    return lstFiles.CheckedItems.Count != 0;
}
2. Add the use of InvokeRequired and Invoke:
C#:
private bool AreAnyItemsChecked()
{
    if (lstFiles.InvokeRequired)
    {
        // We are on a secondary thread so reinvoke the same method on the UI thread.
        return (bool)lstFiles.Invoke(new Func<bool>(AreAnyItemsChecked));
    }
    else
    {
        // We are on the UI thread so perform the desired action.
        return lstFiles.CheckedItems.Count != 0;
    }
}
3.在以前有问题代码的地方调用该方法:
C#:
do
{
    Thread.Sleep(50);
}
while (AreAnyItemsChecked());
 

aaaron123

会员
已加入
2021年1月3日
留言内容
13
编程经验
1-3
这很让人佩服。像魅力一样工作!

Only one typo, I think 之一 AreAnyItemsChecked was meant to start with lower case.

谢谢


附言如何将其标记为已回答?

P.P.S.我对错误投了反对票,然后投票赞成,然后标记为解决方案。不确定,但我猜最后一个是我问的。
 
Last edited:

约翰·H

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
1,028
地点
挪威
编程经验
10+
如何将其标记为已回答?
右上:
1609703596207.png
(我只是点击了它)

它将线程前缀更改为"Resolved".
 

金西尼

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
3,501
地点
悉尼,澳大利亚
编程经验
10+
I think 之一 AreAnyItemsChecked was meant to start with lower case.
不。这是C#,不是Java或JavaScript。任何人都可以使用他们想要的任何约定,但是Microsoft建议方法名称使用Pascal大小写。据我所知,这就是他们在整个.NET Framework中使用的东西,也是绝大多数C#开发人员使用的东西。对于您来说,使用以大写字母开头的系统或第三方方法时,以小写字母开头的方法名称会引起不一致,并且不一致总是很糟糕的。

编辑:我注意到你说"之一 AreAnyItemsChecked",所以我不确定您是否在说我以为是。我看到您用一个小写的前导字母命名了自己的方法,因此我假设您的意思是应该这样命名方法。也许您确实这样做了,但是现在我想知道您是否专门提到了这一点:
C#:
return (bool)lstFiles.Invoke(new Func<bool>(AreAnyItemsChecked));
In that line, it is still referring to the same method but it is not actually calling a method. That is known as a method group and it is how you create a delegate in C#. It's not calling the method at the time but it is saying that this is the method that will be executed when this delegate is invoked. The Invoke method of the control takes that delegate object, carries it across the thread boundary to the UI thread and invokes it, which then executes the specified method on the UI thread.
 
Last edited:

aaaron123

会员
已加入
2021年1月3日
留言内容
13
编程经验
1-3
这很让人佩服。像魅力一样工作!

Only one typo, I think 之一 AreAnyItemsChecked was meant to start with lower case.

谢谢


附言如何将其标记为已回答?

P.P.S.我对错误决定投下反对票,然后投票赞成,然后标记为解决方案。
P.P.P.S忽略错字注释。参见JohnH的回复
 
Last edited:

aaaron123

会员
已加入
2021年1月3日
留言内容
13
编程经验
1-3
不。这是C#,不是Java或JavaScript。任何人都可以使用他们想要的任何约定,但是Microsoft建议方法名称使用Pascal大小写。据我所知,这就是他们在整个.NET Framework中使用的东西,也是绝大多数C#开发人员使用的东西。对于您来说,使用以大写字母开头的系统或第三方方法时,以小写字母开头的方法名称会引起不一致,并且不一致总是很糟糕的。

编辑:我注意到你说"之一 AreAnyItemsChecked",所以我不确定您是否在说我以为是。我看到您用一个小写的前导字母命名了自己的方法,因此我假设您的意思是应该这样命名方法。也许您确实这样做了,但是现在我想知道您是否专门提到了这一点:
C#:
return (bool)lstFiles.Invoke(new Func<bool>(AreAnyItemsChecked));
In that line, it is still referring to the same method but it is not actually calling a method. That is known as a method group and it is how you create a delegate in C#. It's not calling the method at the time but it is saying that this is the method that will be executed when this delegate is invoked. The Invoke method of the control takes that delegate object, carries it across the thread boundary to the UI thread and invokes it, which then executes the specified method on the UI thread.
感谢您的完整答复。就像我在其他地方说过的那样,错字是故意的,但不正确。
 
最佳 底部