前提・実現したいこと
以前も似たようなご質問をさせていただきましたが、再度質問させていただきます。
以前の質問
C#でUSB接続でシリアル通信を行うWindowsアプリを作成しています。
同時に複数のデータが来た場合に対応するために、マルチスレッドに変更したいと思っております。
が、恥ずかしながらマルチスレッドの実装を行ったことがなく、ググってもイマイチだったため、
皆さまのお力を借りたいと思いました。
現状は、データが2回来て正常なデータとするため、同時に来た場合にさばけない状態となっています。
(先勝ちな状態です。)
データの一連の流れは、下記になります。
①データ受信[1回目]
②データ受信[2回目] ← ここでデータ確定
③受信データをAPI経由でDBへ格納
④戻り値を受信元へ送信
該当のソースコード
C#
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.IO.Ports; using System.Net.Http; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Xml.Linq; namespace App { public partial class Form : Form { private SerialPort serialPort; // APIパス private const string API_PATH = @"http://XXXXX"; private int iRetry = 1; private int iSeq = 0; private string sBefData = string.Empty; private string sData = string.Empty; private string sVal1 = string.Empty; private string[] sReturnVal = new string[2]; private bool bFirst = true; readonly string sPath = AppDomain.CurrentDomain.BaseDirectory; private string sFilePathBefore; string sLogFolder = "LogFile"; private bool bSuccess = false; public Form() { InitializeComponent(); } /// <summary> /// フォームロード時イベント /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form_Load(object sender, EventArgs e) { string[] ports = SerialPort.GetPortNames(); foreach (string port in ports) { this.cmbSerials.Items.Add(port); } if (0 < this.cmbSerials.Items.Count) { this.cmbSerials.SelectedIndex = 0; } } /// <summary> /// 接続ボタン押下時イベント /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnConnect_clicked(object sender, EventArgs e) { if (this.cmbSerials.SelectedItem != null && this.serialPort == null) { // COMポートをOPEN serialPort = new SerialPort(); serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort1_DataReceived); serialPort.PortName = this.cmbSerials.SelectedItem.ToString(); serialPort.BaudRate = 19200; serialPort.DataBits = 8; serialPort.Parity = Parity.None; serialPort.StopBits = StopBits.One; serialPort.Encoding = Encoding.UTF8; try { serialPort.Open(); } catch (Exception ex) { } } } /// <summary> /// データ受信時イベント /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void SerialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { if (serialPort != null && serialPort.IsOpen) { try { // 受信データを読み込む SerialPort sp = (SerialPort)sender; string sChildData = sp.ReadExisting(); if (sChildData.Length == 2 && bFisrst) { sVal1 = sChildData; } else { sData = sChildData; if (bFirst) { return; } } if (!string.IsNullOrEmpty(sData) && !string.IsNullOrEmpty(sVal1)) { if (0 < sData.Length) { if (string.IsNullOrEmpty(sBefData) || sBefData != sData) { var parameters = new Dictionary<string, string>() { // APIへ渡すデータセット }; var content = new FormUrlEncodedContent(parameters); try { sReturnVal = GetResponseAPI(API_PATH, content); sBefData = sData; bSuccess = true; } catch { bSuccess = false; } if (bSuccess) { if (0 < sReturnVal.Length) { try { // 送信元へデータ送信 } catch (Exception ex) { } } else { this.iRetry = 1; } } sData = string.Empty; sVal1 = string.Empty; sReturnVal = new string[]{ }; } } } } catch (Exception ex) { } } } /// <summary> /// 終了ボタン押下時イベント /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnFinish_clicked(object sender, EventArgs e) { if (serialPort != null && serialPort.IsOpen) { serialPort.Close(); serialPort = null; } } /// <summary> /// APIをたたいてレスポンスを取得 /// </summary> private string[] GetResponseAPI(string sApiUrl, FormUrlEncodedContent sContent) { string[] sVal = new string[2]; var task = Task.Run(() => { return HttpPost(sApiUrl, sContent); }); string response = task.Result; JArray data = (JArray)JsonConvert.DeserializeObject(response); foreach (JObject obj in data) { JValue did = (JValue)obj["device_id"]; JValue val = (JValue)obj["return_data"]; sVal[0] = (string)did.Value; sVal[1] = (string)val.Value; } return sVal; } /// <summary> /// APIをPOSTする /// </summary> /// <param name="sUrl">APIのURL</param> /// <param name="fContent">引数をエンコードしたもの</param> /// <returns></returns> async public Task<string> HttpPost(string sUrl, FormUrlEncodedContent fContent) { var client = new HttpClient(); var response = await client.PostAsync(sUrl, fContent); return await response.Content.ReadAsStringAsync(); } } }
補足情報(FW/ツールのバージョンなど)
Windows 10
Visual Studio 2017
c#/Windows Form/.Net Framewrok 4.7.1
まだ回答がついていません
会員登録して回答してみよう