i'm trying create application communicates hardware via serial port , reports results gui.
currently moving through gui made keyevents trigger drawing of next "page" of gui. @ 1 step (after key pressed) need draw new page , send few commands via serial port.
the command sending done via :
port.write(data, 0, data.length);
i wait answer waiting datareceivedhandler trigger - pins out there data awaiting , data being processed in method.
at first put sending & receiving command in function drawing page after "draw parts" made stuck - data being transfered, page wasn't drawn - frozen.
then made async method :
private async void senddata() { await task.run(() => serialclass.sendandreceive(command)); // process reply etc. }
which used :
public void loadpage() { image = image.fromfile(path); //do stuff on image using graphics, adding texts etc. picturebox1.image = image; senddata(); }
it works fine, need "reload" page (to call again loadpage). if inside async method :
private async void senddata() { await task.run(() => serialclass.sendandreceive(command)); // process reply etc. loadpage(); }
then image won't refreshed, though data send via serial port. possible somehow check if async function finished , trigger event reload page?
so far i've tried using backgroundworker work complete , property change. data send again, image wasn't reloaded. idea how can achieve that?
thanks in advance help, best regards
you need use state machine , delegates achieve trying do. see code below, recommend doing in separate thread other main. keep track of state you're in, , when response parse correct callback function , if expecting move onto next send command state.
private delegate void callbackfunction(string response); //our generic delegate private callbackfunction callbackresponse; //instantiate our delegate private statemachine currentstate = atrhbpcalstatemachine.waiting; serialport sp; //our serial port private enum statemachine { waiting, sendcmd1, cmd1response, sendcmd2, cmd2response, error } private void do_state_machine() { switch (statemachine) { case statemachine.waiting: //do nothing break; case statemachine.sendcmd1: callbackresponse = cmd1response; //set our delegate first response sp.write("send first command1"); //send our command through serial port currentstate = statemachine.cmd1response; //change cmd1 response state break; case statemachine.cmd1response: //waiting response....you can put timeout here break; case statemachine.sendcmd2: callbackresponse = cmd2response; //set our delegate second response sp.write("send command2"); //send our command through serial port currentstate = statemachine.cmd2response; //change cmd1 response state break; case statemachine.cmd2response: //waiting response....you can put timeout here break; case statemachine.error: //error occurred break; } } private void cmd1response(string s) { //parse string, make sure expect //if is, set next state run next command if(s.contains("expected")) { currentstate = statemachine.sendcmd2; } else { currentstate = statemachine.error; } } private void cmd2response(string s) { //parse string, make sure expect //if is, set next state run next command if(s.contains("expected")) { currentstate = statemachine.waiting; backgroundworker1.cancelasync(); } else { currentstate = statemachine.error; } } //in case, build string builder until carriage return or colon character. tells me //i got characters want response. call delegate calls correct response //function. datareceived event can fire mid response, need someway know when have whole //message. private void serialport1_datareceived(object sender, system.io.ports.serialdatareceivedeventargs e) { string currentline = ""; string data = serialportsensor.readexisting(); data.replace("\n", ""); foreach (char c in data) { if (c == '\r' || c == ':') { sb.append(c); currentline = sb.tostring(); sb.clear(); callbackresponse(currentline); //calls our correct response function depending on current delegate assigned } else { sb.append(c); } } }
i put in background worker, , when press button or can set current state sendcmd1
.
button press
private void buttonstart_click(object sender, eventargs e) { if(!backgroundworker1.isbusy) { currentstate = statemachine.sendcmd1; backgroundworker1.runworkerasync(); } }
background worker work event
private void backgroundworker1_dowork(object sender, doworkeventargs e) { while (true) { if (backgroundworker1.cancellationpending) break; do_state_machine(); thread.sleep(100); } }
edit: can use invoke update gui background worker thread.
this.invoke((methodinvoker)delegate { image = image.fromfile(path); //do stuff on image using graphics, adding texts etc. picturebox1.image = image; });
Comments
Post a Comment