参考
競馬ソフト開発体験教室(https://jra-van.jp/dlb/sdv/trial.html)
Lesson.4 JV-Dataのダウンロード/読み込み進捗状況を表示する
注:上記の参考サイトを元にVBからC#へ移植する進めていきます。
前回記事
JV-LinkをC#で使ってみる(WinForms版) ~3.JV-Dataの内容を読み出す~
今回のソースコード
source – JV-LinkをC#で使ってみる(WinForms版) ~4.JV-Dataのダウンロード/読み込み進捗状況を表示する~
開発環境
- Windows7 64ビット版
- Visual Studio Community 2017
- JV-Link Ver.4.5.1
フォームの編集
進捗表示の作成
フォームデザイナーで[ツールボックス]から「ProgressBar」を2つ貼り付けます。
「ProgressBar」の設定を以下のように変更します。
ダウンロード進捗用プログレスバー(上)
プロパティ | 値 |
---|---|
(Name) | prgDownload |
データ読み込み進捗用プログレスバー(下)
プロパティ | 値 |
---|---|
(Name) | prgJVRead |
タイマーの追加
フォームデザイナーで[ツールボックス]から「Timer」を貼り付ます。
「Timer」の設定を以下のように変更します。
プロパティ | 値 |
---|---|
(Name) | tmrDownload |
Enabled | False |
Interval | 500 |
コードの編集
今回のプログラムは「進捗表示」と「タイマー処理(進捗確認)」になります。
- データ取得ボタンでは、データ読み込みの処理を行っています。
- タイマー処理では、 JV-Link によるダウンロードの完了を監視しています。
データ取得ボタンのコード修正
今回はデータ取得ボタン実行時のコードには JV-Link 関係の関数の追加はありません。基本的には、JVOpen()で得たデータ読み込み数を最大値としてプログレスバーの表示について1ループ毎に1ずつ増加する処理を行っています。また、データ取得処理のdoループ内ではダウンロードが完了するまではcase -3: // ダウンロード中
としてデータ読み込み処理を保留しています。
private void btnGetJVData_Click(object sender, EventArgs e)
{
int nReturnCode;
try
{
string strDataSpec; // JVOpen: ファイル識別子
string strFromTime; // JVOpen: データ提供日付
int nOption; // JVOpen: オプション
int nReadCount; // JVOpen: 戻り値
/* int nDownloadCount; */ // JVOpen: 総ダウンロードファイル数
string strLastFileTimestamp; // JVOpen: 最新ファイルのタイムスタンプ
int nBuffSize = 110000; // JVRead: データ格納バッファサイズ
int nNameSize = 256; // JVRead: ファイル名サイズ
string strBuff; // JVRead: データ格納バッファ
string strFileName; // JVRead: ダウンロードファイル名
JV_RA_RACE RaceInfo = new JV_RA_RACE(); // レース詳細情報構造体
// 進捗表示初期設定
tmrDownload.Enabled = false; // タイマー停止
prgDownload.Value = 0; // JVData ダウンロード進捗
prgJVRead.Value = 0; // JVData 読み込み進捗
// 引数設定
strDataSpec = "RACE";
strFromTime = "20050301000000";
nOption = 2;
nReadCount = 0;
nDownloadCount = 0;
// JVLink ダウンロード処理
nReturnCode = AxJVLink1.JVOpen(strDataSpec, strFromTime, nOption, ref nReadCount, ref nDownloadCount, out strLastFileTimestamp);
// エラー判定
if (nReturnCode != 0)
{
MessageBox.Show("JVOpen エラー:" + nReturnCode);
}
else
{
MessageBox.Show(
"戻り値 : " + nReturnCode + "\n" +
"読み込みファイル数 : " + nReadCount + "\n" +
"ダウンロードファイル数 : " + nDownloadCount + "\n" +
"タイムスタンプ : " + strLastFileTimestamp);
// 進捗表示プログレスバー最大値設定
if (nDownloadCount == 0)
{
prgDownload.Maximum = 100; // ダウンロード必要無し
prgDownload.Value = 100;
}
else
{
prgDownload.Maximum = nDownloadCount;
tmrDownload.Enabled = true; // タイマー開始
}
prgJVRead.Maximum = nReadCount;
if (nReadCount > 0)
{
bool flg_exit = false;
do
{
// バックグラウンドでの処理を実行
Application.DoEvents();
// バッファ作成
strBuff = new string('\0', nBuffSize);
strFileName = new string('\0', nNameSize);
// JVRead で1行読み込み
nReturnCode = AxJVLink1.JVRead(out strBuff, out nBuffSize, out strFileName);
// リターンコードにより処理を分枝
switch (nReturnCode)
{
case 0: // 全ファイル読み込み終了
prgJVRead.Value = prgJVRead.Maximum;
flg_exit = true;
break;
case -1: // ファイル切り替わり
prgJVRead.Value = prgJVRead.Value + 1;
break;
case -3: // ダウンロード中
break;
case -201: // JVInit されてない
MessageBox.Show("JVInit が行われていません。");
flg_exit = true;
break;
case -203: // JVOpen されてない
MessageBox.Show("JVOpen が行われていません。");
flg_exit = true;
break;
case -503: // ファイルがない
MessageBox.Show(strFileName + "が存在しません。");
flg_exit = true;
break;
case int ret when ret > 0: // 正常読み込み
if (strBuff.Substring(0, 2) == "RA") // レコード種別 ID の識別
{
// レース詳細のみ処理
// レース詳細構造体への展開
RaceInfo.SetDataB(ref strBuff);
// データ表示
rtbData.AppendText(
"年:" + RaceInfo.id.Year +
" 月日:" + RaceInfo.id.MonthDay +
" 場:" + RaceInfo.id.JyoCD +
" 回次:" + RaceInfo.id.Kaiji +
" 日次:" + RaceInfo.id.Nichiji +
" R:" + RaceInfo.id.RaceNum +
" レース名:" + RaceInfo.RaceInfo.Ryakusyo10 +
"\n");
}
break;
}
}
while (!flg_exit);
}
// タイマ有効時は、無効化する
if (tmrDownload.Enabled == true)
{
tmrDownload.Enabled = false;
prgDownload.Value = prgDownload.Maximum;
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
return;
}
// JVLink 終了処理
nReturnCode = AxJVLink1.JVClose();
if (nReturnCode != 0)
{
MessageBox.Show("JVClose エラー:" + nReturnCode);
}
}
< 前回からの更新点 >
- 18行目
nDownloadCountはタイマー内でも利用する為、メインフォームのメンバ変数として宣言します。
private int nDownloadCount; // JVOpen 総ダウロードファイル数
- 72行目
nDownloadCountをメインフォームのメンバ変数として宣言したので、元の変数は削除します。
/* int nDownloadCount; */ // JVOpen: 総ダウンロードファイル数
- 81~84行目
プログレスバー関連の変数の初期化を行っています。
// 進捗表示初期設定
tmrDownload.Enabled = false; // タイマー停止
prgDownload.Value = 0; // JVData ダウンロード進捗
prgJVRead.Value = 0; // JVData 読み込み進捗
- 109~120行目
ここでもプログレスバー関連の変数の初期化初期化を行っていますが、特にダウンロードの必要があるかどうかによって条件を分岐しています。
// 進捗表示プログレスバー最大値設定
if (nDownloadCount == 0)
{
prgDownload.Maximum = 100; // ダウンロード必要無し
prgDownload.Value = 100;
}
else
{
prgDownload.Maximum = nDownloadCount;
tmrDownload.Enabled = true; // タイマー開始
}
prgJVRead.Maximum = nReadCount;
- 127~128行目
ループ中にイベント処理をOSへ返してあげます。
// バックグラウンドでの処理を実行
Application.DoEvents();
- 140~143行目
プログレスバーの読み込み進捗表示を完了の値にします。(全てのファイルを処理し終わった為)
case 0: // 全ファイル読み込み終了
prgJVRead.Value = prgJVRead.Maximum;
flg_exit = true;
break;
- 144~146行目
プログレスバーの読み込み進捗表示を1増加させます。(次のファイルに切り替わった為)
case -1: // ファイル切り替わり
prgJVRead.Value = prgJVRead.Value + 1;
break;
- 185~190行目
使い終わったタイマーを終了します。
// タイマ有効時は、無効化する
if (tmrDownload.Enabled == true)
{
tmrDownload.Enabled = false;
prgDownload.Value = prgDownload.Maximum;
}
タイマーのコードの追加
タイマーコードの修正には、以下の「tmrDownload」をダブルクリックします。
タイマー関数内には新たに JV-Link の関数「JVStatus()」を使用します。タイマーによって500ミリ秒ごとにJVStatus()によって JV-Link がどの程度ダウンロード完了したのかを確認し、プログレスバーの表示を更新処理を行います。
private void tmrDownload_Tick(object sender, EventArgs e)
{
int nReturnCode; // JVLink 返値
// JVLink ダウンロード進捗率
nReturnCode = AxJVLink1.JVStatus(); // ダウンロード済のファイル数を返す
// エラー判定
if (nReturnCode < 0)
{
// エラー
MessageBox.Show("JVStatus エラー:" + nReturnCode);
// タイマー停止
tmrDownload.Enabled = false;
// JVLink 終了処理
nReturnCode = AxJVLink1.JVClose();
if (nReturnCode != 0) MessageBox.Show("JVClse エラー:" + nReturnCode);
}
else if (nReturnCode < nDownloadCount)
{
// ダウンロード中
// プログレス表示
prgDownload.Value = nReturnCode;
}
else if (nReturnCode == nDownloadCount)
{
// ダウンロード完了
// タイマー停止
tmrDownload.Enabled = false;
// プログレス表示
prgDownload.Value = nReturnCode;
}
}
コードの修正が完了したらプログラムを実行し、データ取得ボタンを選択して動作を確認します。
以上で、 JV-Data のダウンロードと読み込み進捗表示が完了となります。
プログレスバーが付いた事で、見た目がアプリケーションらしくなりました。