【解決方法】writemultiplecoilsasync で async await タスクを実行するには?

プログラミングQA


WriteMultipleCoilsAsync タスクを実行するには、いくつかの助けが必要です。 Task.Run ステートメントで暗黙的に型指定された変数に void を割り当てられませんというエラー メッセージが表示されます。 WriteMultipleCoilsAsync からの応答メッセージをキャプチャする必要があります。

ここにコード:

C#
private async void btnWriteMultipleCoils_Click(object? sender, EventArgs e)
    {
        string discretes = "true,false,true";
        bool[] diarray = Array.ConvertAll(discretes.Split(','), bool.Parse);
        var response = await Task.Run(() => master.WriteMultipleCoilsAsync(0, diarray));
        await Task.CompletedTask;
    }

WriteMultipleCoilsAsync タスクは次のとおりです。

C#
public Task WriteMultipleCoilsAsync(ushort startAddress, bool[] data)
    {
        return WriteMultipleCoilsAsync(0, startAddress, data);
    }

WriteMultipleCoilsAsync タスクは次のとおりです。

C#
public Task WriteMultipleCoilsAsync(byte slaveAddress, ushort startAddress, bool[] data)
    {
        ValidateData("data", data, 1968);
        WriteMultipleCoilsRequest request = new WriteMultipleCoilsRequest(slaveAddress, startAddress, new DiscreteCollection(data));
        return PerformWriteRequestAsync<WriteMultipleCoilsResponse>(request);
    }

私が試したこと:

何度も試みましたが、今のところ何も機能していません。

解決策 1

ここには多くの間違いがあります。
1. 待ちたいメソッドがマークされていない async

2. への非同期呼び出し PerformWriteRequestAsync メソッドで WriteMultipleCoilsAsync ではありません await編。

あなたが持っている必要があります:

C#
private async void btnWriteMultipleCoils_Click(object? sender, EventArgs e)
{
	string discretes = "true,false,true";
	bool[] diarray = Array.ConvertAll(discretes.Split(','), bool.Parse);
	.. bad! following two lines will lock the UI negating the benefits of asychronous programming
	// var response = await Task.Run(() => master.WriteMultipleCoilsAsync(0, diarray));
	// await Task.CompletedTask;
	
	// asynchronous call + force off UI thread
	var response = await master.WriteMultipleCoilsAsync(0, diarray).ConfigureAwait(false);
}

public async Task<WriteMultipleCoilsResponse> WriteMultipleCoilsAsync(ushort startAddress, bool[] data)
{
	return await WriteMultipleCoilsAsync(0, startAddress, data).ConfigureAwait(false);
}

public async Task<WriteMultipleCoilsResponse> WriteMultipleCoilsAsync(byte slaveAddress, ushort startAddress, bool[] data)
{
	ValidateData("data", data, 1968);
	WriteMultipleCoilsRequest request = new WriteMultipleCoilsRequest(slaveAddress, startAddress, new DiscreteCollection(data));
	return await PerformWriteRequestAsync<WriteMultipleCoilsResponse>(request).ConfigureAwait(false);
}

警告
async void 危険です。 それは 電話して忘れる 非同期呼び出し。 呼び出しが完了するまで UI を待機させたい場合は、 isBusy 要件に応じてブール変数またはコールバック メソッドを使用して、呼び出し状態を追跡および管理します。

ここでもっと読むことができます: C# での非同期プログラミング | マイクロソフト ラーン[^] または、このビデオをご覧ください: C# と Visual Basic の非同期のベスト プラクティス – YouTube[^] – ビデオでは、問題とその修正方法について説明します。 Mads は C# 言語の設計者の 1 人であり、学ぶには最高の人物です。

お役に立てれば!

解決策 2

Graeme (解決策 1) は正しいです。 避ける async void[^] 可能な限り。 残念ながら、それは実際の問題に対処していません。

お二人 WriteMultipleCoilsAsync メソッドが戻る Task、 いいえ Task<T>. つまり、から返される結果がないことを意味します Task. あなたはできる await いつ完了したかを知ることができますが、あなたの中に保存するものは何もありません response 変数。

あなたの PerformWriteRequestAsync<WriteMultipleCoilsResponse> メソッドは Task<WriteMultipleCoilsResponse>の両方のオーバーロードを更新するだけです。 WriteMultipleCoilsAsync 同じものを返すメソッド:

C#
public Task<WriteMultipleCoilsResponse> WriteMultipleCoilsAsync(ushort startAddress, bool[] data)
{
    return WriteMultipleCoilsAsync(0, startAddress, data);
}

public Task<WriteMultipleCoilsResponse> WriteMultipleCoilsAsync(byte slaveAddress, ushort startAddress, bool[] data)
{
    ValidateData("data", data, 1968);
    WriteMultipleCoilsRequest request = new WriteMultipleCoilsRequest(slaveAddress, startAddress, new DiscreteCollection(data));
    return PerformWriteRequestAsync<WriteMultipleCoilsResponse>(request);
}

を避けるために async void、これを呼び出すコードを別の Task・返却方法:

C#
private async Task WriteMultipleCoilsAsync()
{
    string discretes = "true,false,true";
    bool[] diarray = Array.ConvertAll(discretes.Split(','), bool.Parse);
    
    // Or, more simply:
    // bool[] diarray = { true, false, true };

    var response = await master.WriteMultipleCoilsAsync(0, diarray);
    // Do something with the response here...
}

次に、このタスクを返すことを「起動して忘れる」ことができます async コンパイラの警告を回避するために「破棄」を使用して、イベント ハンドラーからメソッドを呼び出します。

C#
private void btnWriteMultipleCoils_Click(object? sender, EventArgs e)
{
    _ = WriteMultipleCoilsAsync();
}

コメント

タイトルとURLをコピーしました