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 이벤트를 사용하여 시도 되세요/questions/2097284/update-ui-multiple-worker-threads-net? –

답변

0

TextBox 업데이트가 백그라운드 스레드에서 제공되므로 실패합니다. 당신은 디스패처를 호출하여 텍스트 상자 업데이트를 감싸는 경우 다음 UI 스레드 틱에서 코드를 실행하고 제대로 업데이트해야합니다 :

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