【问题标题】:C# Process.Start Causing AccessViolationException RandomlyC# Process.Start 随机导致 AccessViolationException
【发布时间】:2022-07-04 18:36:24
【问题描述】:

我已经解决这个问题 3 个月了。

我在本机调试中遇到错误:

"在 FileReader.exe 中的 0x5A222FC2 (comct123.dll) 处引发异常: 0xC0000005:访问冲突读取位置0x0000000C。”

正常调试:

System.Windows.Forms.dll 中的“System.AccessViolationException”

我的设置很简单:

public static Form_Interface Interface;

public static void Initialize()
{
    Application.SetCompatibleTextRenderingDefault(false);
    Interface = new Form_Interface();
    Interface.Filesdgv.DataSource = File.SortableBindingList;
    Application.Run(Interface);
}

看起来很简单,对吧?不。 所以基本上我有一个简单的事件,它只是使用 Process.Start() 打开文件,无论我做什么,它都会在 System.Windows.Forms.dll 中随机崩溃,并出现“System.AccessViolationException”:

private void Filesdgv_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    Filesdgv.Invoke((Action)(() =>
    {
        try
        {
            int rowIndex = e.RowIndex;

            if (rowIndex >= 0)
            {
                int columnIndex = e.ColumnIndex;
                File file = (File)((DataGridView)sender).Rows[rowIndex].DataBoundItem;

                switch (columnIndex)
                {
                    case 0:
                        {
                            Process.Start(file.Location);
                        }
                        break;
                }
            }
        }
        catch
        {
            // This fking catch never works anyway.
        }
    }));
}

private void FileInterface_Load(object sender, EventArgs e)
{
    foreach (string oCurrent in Directory.GetFiles(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "Files To Check")))
        if (oCurrent.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase))
            new File(oCurrent.Split('\\').Last(), oCurrent);
}

我打开文件/链接或其他任何东西都没有关系,它仍然以相同的方式运行。 链接和文件位置也是只读字段。

我有许多其他用途来读取行数据,它永远不会崩溃,即使我点击 10000 次垃圾邮件,它只会随机崩溃 Process.Start()

我尝试过的事情:

  • 使用 BeginInvoke
  • 使用调用
  • 不使用 Invoke/BeginInvoke
  • 在读取之前将文件链接放入字符串中。
  • 使用多个 Try Catch
  • 在另一台机器上重新编码...同样的结果。
  • 我尝试使用 File.Open(要么不打开文件,要么抛出同样的错误 lmao)
  • 尝试使用 [HandleProcessCorruptedStateExceptions],仍然无法捕获异常。
  • 不管我点击慢还是快,仍然有 1/30 的机会发生。
  • 尝试放置 Task.Run(() => Process.Start());您认为线程会保护您免受异常影响吗?没有仍然崩溃...

文件类如下所示:

public class File
{
    public static SortableBindingList<File> SortableBindingList = new SortableBindingList<File>(new List<File>());
    public readonly string fileName;
    public readonly string filePath;
    
    public void AddRow()
    {
        Client.Interface.Invoke((Action)(() =>
        {
            lock (SortableBindingList)
                if (!SortableBindingList.Contains(this))
                    SortableBindingList.Add(this);
        }));
    }

    public string FileName
    {
        get
        {
            return fileName;
        }
    }

    public string Location
    {
        get
        {
            return filePath;
        }
    }
    public File(string fileName, string filePath)
    {
        this.fileName = fileName;
        this.filePath = filePath;
        AddRow();
    }
}

Initalize() 在静态 void Main(string[] args) 中调用。 没有其他线程在运行编辑或类似的东西,唯一运行的线程是表单线程。等待用户输入。

我正在寻找的解决方案:

  • 启动文件/超链接的替代方法。
  • 一种避免表单崩溃的方法(尝试 catch 样式)

即使使用静态数据也会崩溃!:

其他线程正在运行,尽管这些线程不是由我启动的。

【问题讨论】:

  • 您应该为您在此处提供的 sn-p 提供上下文。 - 何时/何地调用Initialize()?什么叫它?什么是List&lt;File&gt;?什么填充它,用什么填充?为什么要存储 Form 的静态实例?为什么要更改子控件的访问修饰符? -- 你到底为什么在事件处理程序中使用Invoke(),并使用引发事件的相同控件?你为什么要尝试调用? -- Thread.Run() 不存在,你的意思是 Task.Run() -- 看起来你最终在某处取消引用空指针,丢失的上下文可能解释了它的原因/原因。
  • 添加了更多细节,使用调用,因为我不知道问题是什么,但你说得对,我不需要它们。是的,我的意思是 Task.Run()
  • 仍然缺少:什么填充 (static) BindingList 以及何时/如何,因为它被初始化为空?为什么该表单声明为static?为什么 DGV 的访问修饰符设置为public?您是否尝试从其他地方访问该控件?是否可以从其他任何地方访问此表单?如果有,从哪里来? -- 如果您删除静态声明,并且您只是将 BindingList 传递给该表单的构造函数(添加一个接受 SortableBindingList 对象的构造函数),那么当前操作会发生什么变化?
  • 已编辑 Initialize(),我在某些时候需要将它们公开,因为我在 File 类中有更多属性来返回检测到的语言等,但我现在完全删除了它。哦,我还使用 Invoke 添加行。让我把它加到东西上。
  • 好的,对不起,我不得不在我从头开始编写的两个版本之间切换,一个在我无法复制的 rdp 上,所以我不得不手动输入大部分内容。

标签: c# winforms exception


【解决方案1】:
Task.Run(() =>
{
    Thread.Sleep(100);
    Process.Start("https://www.youtube.com");
});

这解决了我的问题,似乎在单击事件期间尝试立即运行“process.start”时,GUI 失焦+在完全相同的时刻启动新进程会导致异常。 (微软请修复。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多