前提・実現したいこと
以前も似たようなご質問をさせていただきましたが、再度質問させていただきます。
以前の質問
C#でUSB接続でシリアル通信を行うWindowsアプリを作成しています。
同時に複数のデータが来た場合に対応するために、マルチスレッドに変更したいと思っております。
が、恥ずかしながらマルチスレッドの実装を行ったことがなく、ググってもイマイチだったため、
皆さまのお力を借りたいと思いました。
現状は、データが2回来て正常なデータとするため、同時に来た場合にさばけない状態となっています。
(先勝ちな状態です。)
データの一連の流れは、下記になります。
①データ受信[1回目]
②データ受信[2回目] ← ここでデータ確定
③受信データをAPI経由でDBへ格納
④戻り値を受信元へ送信
該当のソースコード
C#
1using Newtonsoft.Json; 2using Newtonsoft.Json.Linq; 3using System; 4using System.Collections.Generic; 5using System.IO; 6using System.IO.Compression; 7using System.IO.Ports; 8using System.Net.Http; 9using System.Reflection; 10using System.Text; 11using System.Threading.Tasks; 12using System.Windows.Forms; 13using System.Xml.Linq; 14 15namespace App 16{ 17 public partial class Form : Form 18 { 19 private SerialPort serialPort; 20 21 // APIパス 22 private const string API_PATH = @"http://XXXXX"; 23 24 private int iRetry = 1; 25 private int iSeq = 0; 26 private string sBefData = string.Empty; 27 private string sData = string.Empty; 28 private string sVal1 = string.Empty; 29 private string[] sReturnVal = new string[2]; 30 private bool bFirst = true; 31 32 readonly string sPath = AppDomain.CurrentDomain.BaseDirectory; 33 private string sFilePathBefore; 34 string sLogFolder = "LogFile"; 35 private bool bSuccess = false; 36 37 public Form() 38 { 39 InitializeComponent(); 40 } 41 42 /// <summary> 43 /// フォームロード時イベント 44 /// </summary> 45 /// <param name="sender"></param> 46 /// <param name="e"></param> 47 private void Form_Load(object sender, EventArgs e) 48 { 49 string[] ports = SerialPort.GetPortNames(); 50 foreach (string port in ports) 51 { 52 this.cmbSerials.Items.Add(port); 53 } 54 if (0 < this.cmbSerials.Items.Count) 55 { 56 this.cmbSerials.SelectedIndex = 0; 57 } 58 } 59 60 /// <summary> 61 /// 接続ボタン押下時イベント 62 /// </summary> 63 /// <param name="sender"></param> 64 /// <param name="e"></param> 65 private void btnConnect_clicked(object sender, EventArgs e) 66 { 67 if (this.cmbSerials.SelectedItem != null && this.serialPort == null) 68 { 69 // COMポートをOPEN 70 serialPort = new SerialPort(); 71 serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort1_DataReceived); 72 serialPort.PortName = this.cmbSerials.SelectedItem.ToString(); 73 serialPort.BaudRate = 19200; 74 serialPort.DataBits = 8; 75 serialPort.Parity = Parity.None; 76 serialPort.StopBits = StopBits.One; 77 serialPort.Encoding = Encoding.UTF8; 78 79 try 80 { 81 serialPort.Open(); 82 } 83 catch (Exception ex) 84 { 85 } 86 } 87 } 88 89 /// <summary> 90 /// データ受信時イベント 91 /// </summary> 92 /// <param name="sender"></param> 93 /// <param name="e"></param> 94 private void SerialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) 95 { 96 if (serialPort != null && serialPort.IsOpen) 97 { 98 try 99 { 100 // 受信データを読み込む 101 SerialPort sp = (SerialPort)sender; 102 string sChildData = sp.ReadExisting(); 103 104 if (sChildData.Length == 2 && bFisrst) 105 { 106 sVal1 = sChildData; 107 } 108 else 109 { 110 sData = sChildData; 111 if (bFirst) { 112 return; 113 } 114 } 115 116 if (!string.IsNullOrEmpty(sData) && !string.IsNullOrEmpty(sVal1)) 117 { 118 if (0 < sData.Length) { 119 if (string.IsNullOrEmpty(sBefData) || sBefData != sData) 120 { 121 var parameters = new Dictionary<string, string>() 122 { 123 // APIへ渡すデータセット 124 }; 125 var content = new FormUrlEncodedContent(parameters); 126 127 try { 128 sReturnVal = GetResponseAPI(API_PATH, content); 129 sBefData = sData; 130 bSuccess = true; 131 } catch { 132 bSuccess = false; 133 } 134 135 if (bSuccess) 136 { 137 if (0 < sReturnVal.Length) 138 { 139 try 140 { 141 // 送信元へデータ送信 142 } 143 catch (Exception ex) 144 { 145 } 146 } 147 else 148 { 149 this.iRetry = 1; 150 } 151 } 152 sData = string.Empty; 153 sVal1 = string.Empty; 154 sReturnVal = new string[]{ }; 155 } 156 } 157 } 158 } 159 catch (Exception ex) 160 { 161 } 162 } 163 } 164 165 /// <summary> 166 /// 終了ボタン押下時イベント 167 /// </summary> 168 /// <param name="sender"></param> 169 /// <param name="e"></param> 170 private void btnFinish_clicked(object sender, EventArgs e) 171 { 172 if (serialPort != null && serialPort.IsOpen) 173 { 174 serialPort.Close(); 175 serialPort = null; 176 } 177 } 178 179 /// <summary> 180 /// APIをたたいてレスポンスを取得 181 /// </summary> 182 private string[] GetResponseAPI(string sApiUrl, FormUrlEncodedContent sContent) 183 { 184 string[] sVal = new string[2]; 185 var task = Task.Run(() => { 186 return HttpPost(sApiUrl, sContent); 187 }); 188 string response = task.Result; 189 JArray data = (JArray)JsonConvert.DeserializeObject(response); 190 foreach (JObject obj in data) 191 { 192 JValue did = (JValue)obj["device_id"]; 193 JValue val = (JValue)obj["return_data"]; 194 sVal[0] = (string)did.Value; 195 sVal[1] = (string)val.Value; 196 } 197 198 return sVal; 199 } 200 201 /// <summary> 202 /// APIをPOSTする 203 /// </summary> 204 /// <param name="sUrl">APIのURL</param> 205 /// <param name="fContent">引数をエンコードしたもの</param> 206 /// <returns></returns> 207 async public Task<string> HttpPost(string sUrl, FormUrlEncodedContent fContent) 208 { 209 var client = new HttpClient(); 210 var response = await client.PostAsync(sUrl, fContent); 211 return await response.Content.ReadAsStringAsync(); 212 } 213 } 214} 215
補足情報(FW/ツールのバージョンなど)
Windows 10
Visual Studio 2017
c#/Windows Form/.Net Framewrok 4.7.1
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/09/15 04:08
2020/09/15 12:20
2020/09/22 23:24