1

我想知道如何異步運行非常長的運行python腳本,以便它不會阻止我的整個應用程序,但我也希望它的流輸出在運行時寫入文本框。我設法弄清楚了第一部分,但不是第二部分。目前,文本框只有在腳本完成後纔會更新。這裏是我的代碼的重要部分:寫入文本框時運行IronPython異步

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,但這不起作用,因爲我的文本框沒有得到實時更新。

+0

您是否嘗試過使用http://stackoverflow.com提到的ProgessChanged事件/問題/ 2097284 /更新的用戶界面,從海報工作者線程網? –

回答

0

由於TextBox更新將在後臺線程中進入,它將失敗。如果你給調度呼叫換你的TextBox的更新將在下一UI線程剔運行的代碼,並應正確更新:

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