System.AccessViolationException发生在TextView.Buffer上 [英] System.AccessViolationException occurs on TextView.Buffer

查看:120
本文介绍了System.AccessViolationException发生在TextView.Buffer上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to show some text on C#, one line per second, using Gtk# GUI. the text is on .txt file, and it has 4 integers at every line.

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

but when I compiled it at DragonFly BSD, the first one or two lines are showed perfectly on textbox but the program halts, and I've got SIGABRT and SIGSEGV errors.

所以我已经在Windows上编译了相同的代码,并且出现了以下错误:"System.AccessViolationException"之类的异常.

so I've compiled same code at Windows, and it has this error: Exception of 'System.AccessViolationException' or something like that.

我检查了允许不安全的代码",但结果是相同的.

I've checked "Allow unsafe codes", but the result was same.

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");
    }
}

代码的其他部分工作正常,但是在这一部分中会发生错误.

The other parts of code works perfectly, but in this part, the error occurs.

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

If I delete 'async' and "await Task.Delay(1000);", it doesn't have error but I want to display it 1 lines per second.

我该如何解决?

推荐答案

Gtk#很有气质,并且在与UI线程(主要线程)混乱的线程中不能很好地工作.另外,您不能从辅助线程更新UI(这对于所有图形工具包都是常见的).

Gtk# is quite temperamental and does not work very well with threads messing with the UI thread (the main one). Also, you cannot update the UI from a secondary thread (this is common for all graphic toolkits).

如果我正确理解了您的问题,则只能使用System.Threading睡眠一秒钟.问题是,如果您这样做了,那么您的应用将在整整一秒钟内都没有响应.

If I understood your problem correctly, you could only just use System.Threading in order to sleep for a second. The problem is, if you did that, your app would be unresponsive for that whole second.

解决方案是主动等待直到一秒钟过去.这比等待一秒钟要精确得多,但我希望它能满足您的需求.

The solution is to actively wait until a second has passed. This is less exact, than waiting for exactly a second, but I hope it will meet your needs.

这是您需要的代码:

    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()),在此目的很方便.在等待时间过去的同时,我们可以重复调用此命令以提供响应迅速的用户界面.

Gtk can run an iteration and return (Gtk.Application.RunIteration()), which is handy for the purpose here. We can call repeately that in order to offer a responsive user interface, while we wait for the time to pass.

如果您对如何使用它有疑问,这是完成任务所需的窗口的全部代码.

And here is the whole code for a window doing the task you need, in case you have doubts about how to use it.

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;
}

希望这会有所帮助.

这篇关于System.AccessViolationException发生在TextView.Buffer上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆