(または、1023 で割り切れる場合 (以下の Update 3 を参照))
フェッチされるデータを含むファイルのサイズが 1024 で割り切れる場合に発生するバグを追跡しています。その場合、フェッチは完了するまで機能しているように見えますが、最後に失敗します。
このような場合(サイズが 1024 の倍数のファイルがあった場合)、何かおかしなことが行われているのではないかと考えて、コード内に「1024」への参照がないか検索しましたが、「1024」に具体的に言及しているライブ コードはありません。 ."
取得コードで奇妙に見えるものを 1 つ見つけました。
connFrmSitesData.Dispose();
connFrmSitesData = null;
フォームを null に設定すると、問題が発生する可能性がありますか? それがそこにある理由はまったくありますか?
アップデート
私は不思議に思うこのコードを見つけました:
string theMessage = new string( '\x00', 1023 );
...それが問題に接線的に関与している可能性がある場合.
更新 2
これで、その文字列 (theMessage)* が使用されていないことがわかりました。私はそれをコメントアウトすることができました(同様に宣言され、その後使用されなかった3つの場所すべてで)。
では、なぜこのコードに次のようなものがあるのでしょうか。
bool retVal = false;
string theMessage = new string( '\x00', 1023 ); // fill 1023 bytes with nulls
. . .
if( retVal = Util.NetSendCommand( rc.command ) )
...「retVal」はグレー表示された var (Resharper によると思います) ですが、「theMessage」はグレー表示されていませんか?
クラスに対してプライベートに宣言された「通常の」** theMessage もあります。
プライベート文字列 theMessage;
** 「通常」は、オーバーロードされたコンストラクターでインスタンス化されません。
更新 3
問題の領域を見つけた可能性があります (実際には、別のプロジェクト (プロジェクトが呼び出す .DLL) にあります)。
MAXREAD = 1023 であるため、このコードは疑わしいものです。
正確なサイズのファイルが失敗する原因となる、これに何か問題があることを誰かが見ることができますか? たとえば、前の Read がすべてを取得した場合、bReader.Read() の呼び出しは失敗しますか?
それとも、ここのどこかに別の問題が潜んでいますか?
BinaryReader bReader = null;
. . .
bReader = new BinaryReader( theN_Stream );
. . .
fsWriteText = new FileStream( destFPath, FileMode.Create, FileAccess.Write );
. . .
bWriter = new BinaryWriter( fsWriteText );
. . .
/* --------------------------------------- *
* Incoming message may be larger than
* the buffer size.
* --------------------------------------- */
int index = 0;
int indexLast = 0;
int next2Read = MAXREAD;
try
{
// keep doing this until no data available on the stream, ...
do
{
next2Read = MAXREAD; //1023
longString = "";
Array.Clear( readbuffer, 0, MAXREAD );
numberOfBytesRead = bReader.Read( readbuffer, 0, next2Read );
indexLast = index;
realTotBytesRead += numberOfBytesRead;
index += numberOfBytesRead;
nBytes += numberOfBytesRead;
xferProgress = nBytes.ToString() + "|" + fsize.ToString();
OnProgressChanged(xferProgress);
if( bWriter != null )
{
if( bWriter.BaseStream.CanWrite )
{
bWriter.Write( readbuffer, 0, numberOfBytesRead );
}
}
if( index >= fsize )
{
haveFinishedRead = true;
break;
}
if( !theN_Stream.CanRead )
{
break;
}
} while( index < fsize );
更新 4
この問題の根底に到達しようとして、私は次のメモをまとめました (しゃれた意図はありません)。
// readbuffer はバイト配列です。// bReader はバイナリ リーダーです
「インデックス」は 0 から始まり、読み取られたバイト数 (1023 または残り/最後のビット) が割り当てられ、後でファイルサイズに対してテストされます。等しいかそれより大きい場合、ループは終了します。
「indexLast」は 0 から始まり、最初に index の値が割り当てられます (最初のループでは 0、その後は 1023 または残り/最後のビットのいずれか) が、参照されることはないため、コメント アウトすることができます。
「next2Read」には最初に MAXREAD (1023) が割り当てられます。これは次の行で使用されます。
numberOfBytesRead = bReader.Read( readbuffer, 0, next2Read );
...しかし、その後は参照されないため、削除することができ、上記の行は次のように変更されます。
numberOfBytesRead = bReader.Read( readbuffer, 0, MAXREAD);
"longString" は空の文字列に初期化されますが、どこにも参照されません。ただし、これはグローバル var であるため、この値は別の場所で必要になるのではないでしょうか?
「numberOfBytesRead」には、bReader の Read() メソッドの戻り値が割り当てられます。次に、「index」と「nBytes」に割り当てられます。次に、bWriter.Write() の呼び出しで「書き込むバイト数」として使用されます。
「longString」と同様に、「realTotBytesRead」が割り当てられ、このメソッド内で参照されませんが、グローバル変数であるため、他の場所で使用される可能性があります...
「nBytes」には「numberOfBytesRead」の値が割り当てられ、進行状況バーに使用されます。「numberOfBytesRead」を使用して仲介者を切り取ることができるようですが、「nBytes」は何も害を及ぼさないと思います(頭蓋骨が崩壊するのを防ぐどろどろしたピンク色の灰色のものを除いて)...
「fsize」は条件分岐に使用されます。最初は 0 に設定されており、次のように設定します。
fsize = (int)Int32.Parse( fFileSz );
"fFileSz" は、ファイル サイズ (別の場所に設定) を保持する公開静的文字列です。
「theN_Stream」はネットワーク ストリームです。
コンピューター プログラムをデバッグするときは、どこか探偵のようになりますが、暗い路地で悪役を追跡して犯罪者を暴露するのではなく、悪い振る舞いをしている部分を吸い出します。この種の探偵の仕事は、他の仕事よりもはるかに安全であり、座りがちで落ち着いていますが、靴革を節約して生命保険の保険料を節約することで得られるものは、シナプスの破裂と脳細胞の過剰な吹き飛ばしで失われます。 「雲」を超えて。行う/行わないことには常にトレードオフがあります。
更新 5
このコードは、ファイルサイズが MAXREAD (1023) より小さいか、等しいか、大きいかに関係なく機能するように見えるため、問題は別の場所にあると考えています。擬似コード:
//ファイルサイズ < MAXREAD:
if filesize == 1022:
numberOfBytesRead == 1022
index == 1022;
//....breaks out (as it should, it's done), because index == fsize
//ファイルサイズ == MAXREAD: //1023
if filesize == 1023:
numberOfBytesRead == 1023
index == 1023;
//breaks out (as it should, it's done), because index == fsize
//ファイルサイズ > MAXREAD:
if filesize == 1024:
numberOfBytesRead == 1023
index == 1023;
...continues to loop again:
numberOfBytesRead == 1
index == 1024;
//breaks out (as it should, it's done), because index == fsize
// どのファイルサイズでも同じにする必要があります > MAXREAD
更新 6
「マジック ナンバー」が見つかりました - サイズが 190KB のファイルを処理するとアプリがクラッシュします。フリーズするよりもフェッチ プロセスを示すプログレス バー。それ以外の場合は問題ありません (ファイルサイズが 190KB より小さい場合でも大きい場合でも問題ありません)。
更新 7
これがひどい修正であることは理解していますが、レガシー コードは非常に複雑で、[意図的に?] 難読化されており、DLL が exe を呼び出したり、DLL が exe を呼び出したり、複数のバックグラウンド スレッドが起動したり停止したり、フラッシュしたり、非常識な亡命者からのストロボ ライトのように点滅します。このコードを変更して、この方法で一時的な修正を力ずくで行いました。
if( processMessage )
{
Util.ProcessServerResponse( theMessage.Trim( uDelims.ToCharArray() ) );
}
...これに:
if ( processMessage )
{
string valToPass = theMessage.Trim(uDelims.ToCharArray());
if (valToPass.IndexOf("190980") > 0)
{
valToPass = valToPass.Replace("190980", "190978");
}
Util.ProcessServerResponse( valToPass );
}
// 注: 1) 何らかの理由で、filesize が 190980 の場合、DLL で無限ループが発生し、"index" (既に読み取られたバイト数) が、読み取られる合計バイト数を表す値よりも小さいままになります。その他、または他のすべてのファイルサイズの大部分、正常に動作します... 2) string.Contains() を使用して "190980" を見つけることができませんでした。