写入文本框时运行IronPython异步

时间:2013-05-28 03:46:32

标签: c# windows-phone-7 windows-phone backgroundworker ironpython

我想知道如何异步运行一个运行时间很长的python脚本,这样它就不会阻塞我的整个应用程序,但我也希望它的流输出在运行时写入文本框。我设法弄清楚了第一部分而不是第二部分。目前,文本框仅在脚本完成后才会更新。以下是我的代码的重要部分:

MainPage.xaml.cs中:

...
BoxStream bs = null;

public MainPage()
    {
        InitializeComponent();

        bs = new BoxStream(OutBox);
        ...
    }
...
private bool slice()
    {
        try
        {
            var ipy = Python.CreateEngine();
            var iscp = ipy.CreateScope();
            iscp.SetVariable("rootP", Directory.GetCurrentDirectory());
            ipy.ExecuteFile("Pathsetter.py", iscp);
            var ipath = ipy.GetSysModule().GetVariable("path");

            ScriptEngine m_engine = Python.CreateEngine();
            ScriptScope m_scope = m_engine.CreateScope();
            m_engine.GetSysModule().SetVariable("path", ipath);

            m_engine.Runtime.IO.SetOutput(bs, Encoding.UTF8);
            m_engine.Runtime.IO.SetErrorOutput(bs, Encoding.UTF8);

            /*string dir = Directory.GetCurrentDirectory();
            string ndir = dir.Replace(@"\", @"\\");*/

            m_engine.ExecuteFile(Directory.GetCurrentDirectory() + "\\Skeinforge\\skeinforge_application\\skeinforge_utilities\\skeinforge_craft.py", m_scope);

            string stl_path = Directory.GetCurrentDirectory() + "\\test.stl";
            object func = m_scope.GetVariable("makeGcode");
            object result = m_engine.Operations.Invoke(func, stl_path);

            Debug.WriteLine(result); 
        }
        catch (Exception ex)
        {
            Debug.WriteLine("Py error: " + ex.Message);
            return false;
        }

        return true;
    }
...
private void Slice_Button_Click(object sender, RoutedEventArgs e)
    {
        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += new DoWorkEventHandler(
        delegate(object o, DoWorkEventArgs args)
        {
            BackgroundWorker b = o as BackgroundWorker;

            slice();
        });
    }
...

BoxStream.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;
using System.Windows.Controls;

namespace SkeinforgeWP8
{
    class BoxStream : Stream
    {
        TextBox _OutBox = null;

        public BoxStream(TextBox tBox)
        {
            Debug.WriteLine("Writing stream to box");
            _OutBox = tBox;
            _OutBox.Text = "";
        }

        public override void WriteByte(byte value)
        {
            base.WriteByte(value);
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            _OutBox.Text += Encoding.UTF8.GetString(buffer, offset, count);
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            throw new NotImplementedException();
        }

        public override void SetLength(long value)
        {
            throw new NotImplementedException();
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotImplementedException();
        }

        public override void Flush()
        {
            return;
        }

        public override long Position
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public override long Length
        {
            get { throw new NotImplementedException(); }
        }

        public override bool CanWrite
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { return false; }
        }

        public override bool CanRead
        {
            get { return false; }
        }
    }
}

我想这可能相当简单,但经过大量搜索,我发现的信息告诉我像上面一样使用BackgroundWorker,但这不起作用,因为我的文本框没有获得实时更新。

1 个答案:

答案 0 :(得分:0)

由于TextBox更新将在后台线程上进行,因此它将失败。如果通过调用Dispatcher包装TextBox更新,它将在下一个UI线程tick上运行代码,并应正确更新:

    public override void Write(byte[] buffer, int offset, int count)
    {
        Deployment.Current.Dispatcher.BeginInvoke(() => {
            _OutBox.Text += Encoding.UTF8.GetString(buffer, offset, count);
        });
    }