5

Tôi đang cố gắng sử dụng C# để kiểm soát một ứng dụng nền dòng lệnh, có thể được tải về tại đây: http://www.ti.com/litv/zip/spmc015bException An hoạt động đọc không đồng bộ là đã cơ bản dở dang trên dòng StandardOutput

Đây là một ứng dụng cho điện áp động cơ kiểm soát, khi tôi nhập vào ứng dụng, như "b.exe -c 1", giao diện điều khiển có vẻ là một loại mô hình chặn. Mỗi lệnh trong ứng dụng này bắt đầu bằng ký hiệu "#". Xem bức ảnh ở đây:

http://i46.tinypic.com/zx5edv.jpg

Những gì tôi đang cố gắng để làm được, sử dụng StandardInput.WriteLine ("stat vout"); để đo điện áp. Điều này sẽ gửi một lệnh "stat vout" tới nền console và lý tưởng trả về một giá trị điện áp. Trong pic này, nó trả về một số gợi ý trợ giúp. Duing tất cả thời gian này, nó vẫn còn trong chế độ chặn.

Tôi muốn nhận thông báo trả về với StandardOutput.ReadLine(); nhưng không thành công. Nếu ReadToEnd() thì chương trình của tôi bị đóng băng bởi vì ứng dụng này không bao giờ trở lại giao diện điều khiển chuẩn đang chặn.

Khi tôi thử BeginOutputReadLine(); Sự kiện OutputDataReceived thực sự có thể nhận được thông báo trả về từ bàn điều khiển, như trong các bức ảnh của "stat [vout | vbus | fault". Nhưng nó bị giới hạn trong chương trình chuỗi đơn của tôi.

Tình hình hiện tại của tôi là, tôi sử dụng System.Timers.Timers trong WinForms và mỗi giây sẽ gửi lệnh "stat vout2" để đọc điện áp và hy vọng nhận được giá trị trả lại.

Tuy nhiên, System.Timers.Timers là không đồng bộ, vì vậy khi tôi gọi BeginOutputReadLine() trong chuỗi Timers này, nó nhắc "Một thao tác đọc async đã được bắt đầu trên luồng". Trong khi chờ đợi, như tôi đã trình bày ở trên, tôi không thể sử dụng các phương thức đồng bộ như ReadLine() để lấy giá trị.

Vì vậy, tôi nên làm gì bây giờ? Tôi thực sự cần chạy ứng dụng dòng lệnh này trong chế độ đa luồng.

Cảm ơn bạn rất nhiều và chúc mọi người có một ngày cuối tuần vui vẻ.

--UPDATE vào ngày 28 tháng tư 19:18 CST Đây là mã có liên quan nguồn:

Một trong những WinFroms nút sẽ bắt đầu() Class SystemClock, sau đó Timing.Measuring() được thực hiện mỗi giây. Lớp TimingController sẽ gọi GetVoltage() và GetCurrent() cùng một lúc trong một giây theo SystemClock, để đo điện áp và dòng điện.

Trong lớp đo lường, StandardInput.WriteLine ("stat vout2"); để có được điện áp từ ứng dụng giao diện điều khiển và StandardInput.WriteLine ("stat cur"); để có được dòng điện. Cả hai đều sử dụng BeginOutputReadLine() để có được kết quả từ khi StandardOutput không hoạt động.

Tôi sử dụng cờ isOutputObtained để cho biết dữ liệu có được trả về hay không. Mỗi lần đọc xong, tôi đã gọi hàm CancelOutputRead(); để hủy đọc không đồng bộ.

Nhưng nó vẫn cho tôi ngoại trừ lỗi của "Một hoạt động đọc không đồng bộ là đã cơ bản dở dang trên dòng StandardOutput"

public class SystemClock 
{ 
    TimingController Timing = new TimingController(); 
    private Timer TimerSystemClock; 

    public SystemClock() 
    { 
     TimerSystemClock = new Timer(); 
     TimerSystemClock.Interval = 1000; 
     TimerSystemClock.AutoReset = true; 
     TimerSystemClock.Elapsed += new ElapsedEventHandler(TimerSystemClock_Elapsed); 
     TimerSystemClock.Enabled = false; 
     Timing.ClockInstance = this; 
    } 

    public void Start() 
    { 
     TimerSystemClock.Enabled = true; 
    } 

    void TimerSystemClock_Elapsed(object sender, ElapsedEventArgs e) 
    { 
     Timing.Measuring(); 
    } 
} 

public class TimingController 
{ 
    // Get singleton of Measurement Class 
    Measurement Measure = Measurement.GetInstance();  

    public SystemClock ClockInstance 
    { 
     get { return Clock; } 
     set { Clock = value; } 
    } 

    private void Measuring() 
    { 
     CurrentVoltage = Measure.GetVoltage(); 
     CurrentCurrent = Measure.GetCurrent(); 
    } 
} 

public sealed class Measurement 
{ 
    // Singleton 
    public static readonly Measurement instance = new Measurement(); 
    public static Measurement GetInstance() 
    { 
     return instance; 
    } 

    private Process ProcMeasuring = new Process(); 
    double measureValue 
    bool isOutputObtained; 

    private Measurement() 
    { 
     ProcMeasuring.StartInfo.FileName = "b.exe"; 
     ProcMeasuring.StartInfo.Arguments = "-c 1"; 
     ProcMeasuring.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory(); 
     ProcMeasuring.StartInfo.UseShellExecute = false; 
     ProcMeasuring.StartInfo.RedirectStandardInput = true; 
     ProcMeasuring.StartInfo.RedirectStandardOutput = true; 
     ProcMeasuring.StartInfo.RedirectStandardError = true; 
     ProcMeasuring.StartInfo.CreateNoWindow = true; 
     ProcMeasuring.OutputDataReceived += new DataReceivedEventHandler(MeasurementOutputHandler); 
    } 

    public double GetVoltage(Machine machine) 
    { 
     isOutputObtained = false; 

     ProcMeasuring.StandardInput.WriteLine("stat vout2"); 
     ProcMeasuring.BeginOutputReadLine(); 

     while (!isOutputObtained) 
     { 
      isOutputObtained = true; 
     } 

     return measureValue; 
    } 

    public double GetCurrent(Machine machine) 
    { 
     isOutputObtained = false; 

     ProcMeasuring.StandardInput.WriteLine("stat cur"); 
     ProcMeasuring.BeginOutputReadLine(); 

     while (!isOutputObtained) 
     { 
      isOutputObtained = true; 
     } 

     return measureValue; 
    } 

    private void MeasurementOutputHandler(object sendingProcess, DataReceivedEventArgs outLine) 
    { 
     if (!String.IsNullOrEmpty(outLine.Data) && (outLine.Data != "# ")) 
     {     
      measureCurrentValue = Convert.ToDouble(outLine.Data); 
      isOutputObtained = true; 

      ProcMeasuring.CancelOutputRead(); 
     } 
    } 
} 
+0

Đăng một số mã phù hợp có thể hữu ích. –

+0

Mã của tôi quá dài, tôi sẽ hiển thị nó là câu trả lời mới – Asker

+1

Không, đó không phải là câu trả lời. Đặt nó vào câu hỏi. –

Trả lời

0

Tôi nghĩ rằng bạn có hai lựa chọn.

Nếu bạn không thể bỏ lỡ một mẫu vì mẫu trước đó mất quá nhiều thời gian, sau đó đặt cờ để cho biết bạn đã lấy mẫu.

public class TimingController 
{ 
    // Get singleton of Measurement Class 
    Measurement Measure = Measurement.GetInstance();   

    bool isMeasuring = false; 

    public SystemClock ClockInstance 
    { 
     get { return Clock; } 
     set { Clock = value; } 
    } 

    private void Measuring() 
    { 
     if(isMeasuring) return; 

     isMeasuring = true; 
     CurrentVoltage = Measure.GetVoltage(); 
     CurrentCurrent = Measure.GetCurrent(); 
     isMeasuring = false; 
    } 
} 

Nếu không thể bỏ lỡ một khoảng thời gian, bạn có thể thử tạo đối tượng quy trình mới cho mỗi cuộc gọi thay vì sử dụng lại quy trình hiện có. Điều này có thể tạo ra rất nhiều trẻ em mặc dù nếu các lệnh mất một thời gian dài để hoàn thành.