【问题标题】:System.AccessViolationException occurs on TextView.BufferSystem.AccessViolationException 发生在 TextView.Buffer 上
【发布时间】:2019-10-24 03:54:51
【问题描述】:

我正在尝试使用 Gtk# GUI 在 C# 上显示一些文本,每秒一行。 文本在 .txt 文件中,每行有 4 个整数。

但是当我在 DragonFly BSD 上编译它时,前一两行在文本框上完美显示,但程序停止,并且出现 SIGABRT 和 SIGSEGV 错误。

所以我在 Windows 上编译了相同的代码,它有这个错误:'System.AccessViolationException' 的异常或类似的东西。

我检查了“允许不安全代码”,但结果是一样的。

async void DisplayText(string FileName)
{
    string[] Temp = File.ReadAllLines(FileName);
    string[] ScoreBoard = new string[4];

    TextIter Ti = textview.Buffer.StartIter;

    foreach (string Line in Temp)
    {
        ScoreBoard = Line.Split('\t');

        await Task.Delay(1000);

        textview.Buffer.Insert(ref Ti, ScoreBoard[0]);
        textview.Buffer.Insert(ref Ti, "  |  ");
        textview.Buffer.Insert(ref Ti, ScoreBoard[1]);
        textview.Buffer.Insert(ref Ti, "\t");
        textview.Buffer.Insert(ref Ti, ScoreBoard[2]);
        textview.Buffer.Insert(ref Ti, "  |  ");
        textview.Buffer.Insert(ref Ti, ScoreBoard[3]);
        textview.Buffer.Insert(ref Ti, "\n");
    }
}

其他部分代码完美运行,但是在这部分出现错误。

如果我删除“async”和“await Task.Delay(1000);”,它没有错误,但我想每秒显示 1 行。

我该如何解决?

【问题讨论】:

  • GTK# 不喜欢在主线程之外运行,你是在工作线程中运行它吗?

标签: c# mono monodevelop gtk#


【解决方案1】:

Gtk# 非常喜怒无常,不能很好地处理与 UI 线程(主要线程)混淆的线程。此外,您不能从辅助线程更新 UI(这对所有图形工具包都很常见)。

如果我正确理解了您的问题,您只能使用 System.Threading 来休眠一秒钟。问题是,如果您这样做了,您的应用将在那一秒内无响应。

解决方案是主动等待,直到一秒钟过去。这比等待一秒钟更不准确,但我希望它会满足您的需求。

这是您需要的代码:

    void ActivelyWaitFor(long targetMillis)
    {
        var stopWatch = new System.Diagnostics.Stopwatch();

        stopWatch.Start();

        while( stopWatch.ElapsedMilliseconds < targetMillis ) {
            Gtk.Application.RunIteration();
        }

        stopWatch.Stop();
    }

Gtk 可以运行一次迭代并返回 (Gtk.Application.RunIteration()),这对于这里的目的来说很方便。我们可以重复调用它以提供响应式用户界面,同时等待时间过去。

这里是执行您需要的任务的窗口的完整代码,以防您对如何使用它有疑问。

public class MainWindow: Gtk.Window
{
    public MainWindow()
        :base(Gtk.WindowType.Toplevel)
    {
        this.Build();

        this.DeleteEvent += (o, evt) => Gtk.Application.Quit();
        this.Shown += (o, args) => this.DisplayText();
    }

    void Build()
    {
        this.TextView = new Gtk.TextView();

        this.Add( this.TextView );
    }

    void DisplayText()
    {
        string[] ScoreBoard = new string[4];
        Gtk.TextIter Ti = this.TextView.Buffer.StartIter;
        string[] Temp = {
            "1\t2\t3\t4",
            "1\t2\t3\t4",
            "1\t2\t3\t4",
            "1\t2\t3\t4",
            "1\t2\t3\t4",
            "1\t2\t3\t4",
        };

        foreach (string Line in Temp)
        {
            ScoreBoard = Line.Split('\t');

            this.ActivelyWaitFor( 1000 );

            this.TextView.Buffer.Insert(ref Ti, ScoreBoard[0]);
            this.TextView.Buffer.Insert(ref Ti, "  |  ");
            this.TextView.Buffer.Insert(ref Ti, ScoreBoard[1]);
            this.TextView.Buffer.Insert(ref Ti, "\t");
            this.TextView.Buffer.Insert(ref Ti, ScoreBoard[2]);
            this.TextView.Buffer.Insert(ref Ti, "  |  ");
            this.TextView.Buffer.Insert(ref Ti, ScoreBoard[3]);
            this.TextView.Buffer.Insert(ref Ti, "\n");
        }
    }

    void ActivelyWaitFor(long targetMillis)
    {
        var stopWatch = new System.Diagnostics.Stopwatch();

        stopWatch.Start();

        while( stopWatch.ElapsedMilliseconds < targetMillis ) {
            Gtk.Application.RunIteration();
        }

        stopWatch.Stop();
    }

    private Gtk.TextView TextView;
}

希望这会有所帮助。

【讨论】:

  • 谢谢。请考虑将我的答案标记为解决方案。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2021-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-28
相关资源
最近更新 更多