等待的方法调用似乎没有完成
Awaited method call doesnt appear to complete
我刚开始学习异步编码,运行陷入了困境。
这就是我想要做的。
我有一个异步调用两个等待方法的方法。出于测试目的,每个方法都调用一个执行 WAITFOR DELAY 'xxx'
.
的存储过程
在每个方法调用中,另一个方法需要 运行 在它旁边生成三个加载点附加到传入的文本值。
所以当 await Task.Run(() => DisableReplication("Disable Replication"))
是 运行ning 时(调用存储过程 10 秒)它将显示
Disabling Replication.
Disabling Replication..
Disabling Replication...
直到该存储过程完成,然后它应该说
Disabling Replication - Complete
然后它应该调用 await Task.Run(() => ImportWeights("Importing Weights"))
,例如,proc 需要 20 秒才能完成。所以会显示
Importing Weights.
Importing Weights..
Importing Weights...
然后一旦完成它会说
Import Weights - Complete.
在每个方法中,都有一个布尔值在方法完成后从 false 设置为 true。该值用于 while 循环中的 ShowProgressText
方法。一旦该值设置为 true,它就会爆发。
目前它在显示 'Disabling Replication' 方面做得很好,但是一旦该方法完成,它就会开始在 'Disabling Replication' 和 'Importing Weights' 之间切换。我假设 Disabling Replication 方法已经完成,所以我不确定为什么它会继续拾取文本。我认为问题出在 ShowProgressText
方法上。
有谁知道我做错了什么,也许我能以某种方式简化它吗?
这是一个显示它正在做什么的 .gif,下面是我正在使用的代码。
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DirectMailSpendManagement
{
public partial class FrmRapport : AestheticsFormBase
{
#region Instantiations
private readonly RapportDataAccess access = new RapportDataAccess();
private readonly Panel panel = new Panel();
#endregion
#region Fields
private bool IsCompleted;
#endregion
#region Constructors
public FrmRapport()
{
InitializeComponent();
}
#endregion
#region Private Methods
private void BtnGetRapportFile(object sender, EventArgs e)
{
_ = LoadRapport();
}
private async Task LoadRapport()
{
await Task.Run(() => DisableReplication("Disable Replication"));
await Task.Run(() => ImportWeights("Importing Weights"));
}
private void DisableReplication(string txt)
{
IsCompleted = false;
Task.Run(() => ShowProgressText(txt));
access.DisableReplication();
}
private void ImportWeights(string txt)
{
IsCompleted = false;
Task.Run(() => ShowProgressText(txt));
access.ImportAndCalculateWeights(panel.PanelNumber, "", "", "");
}
private void ShowProgressText(string txt)
{
var count = 0;
var logText = new StringBuilder();
logText.Append(txt);
var baseLen = logText.Length;
while (!IsCompleted)
{
Thread.Sleep(300);
if (count >= 3)
{
logText.Remove(baseLen, count);
count = 0;
}
logText.Append(".");
count++;
BeginInvoke(new Action(() => { UpdateProgressText(logText.ToString()); }));
}
BeginInvoke(new Action(() => { UpdateProgressText(txt + " - Complete"); }));
}
private void UpdateProgressText(string txt)
{
lblProgress.Text = txt;
}
#endregion
}
}
问题是您有两个单独的任务 运行 调用 ShowProgressText。 Task.Run() 不是您通常使用的东西,除非您与不使用 C# async/await 模式的代码交互。所以也许 LoadRapport 可能是这样的:
bool IsCompleted;
string LogText;
private async Task LoadRapport()
{
LogText = "Disable Replication";
IsCompleted = false;
_ = ShowStatus(); // start this task but don't wait for it to finish.
// Start these long running methods on a separate non UI thread using Task.Run.
await Task.Run(() => DisableReplication());
LogText = "Importing Weights";
await Task.Run(() => ImportWeights());
IsCompleted = true; // tell ShowStatus to complete.
}
ShowStatus 可能是这样的:
async Task ShowStatus()
{
while (!IsCompleted) {
BeginInvoke(new Action(() =>
{
UpdateProgressText(this.LogText);
})); ;
await Task.Delay(200);
}
UpdateProgressText("Completed");
}
我还会记得在这个漫长的 运行 过程中禁用调用 BtnGetRapportFile 的按钮,这样用户就不会单击它 10 次并获得 10 个单独的线程 运行 调用您的 SQL 服务器...
我刚开始学习异步编码,运行陷入了困境。
这就是我想要做的。
我有一个异步调用两个等待方法的方法。出于测试目的,每个方法都调用一个执行
的存储过程WAITFOR DELAY 'xxx'
.在每个方法调用中,另一个方法需要 运行 在它旁边生成三个加载点附加到传入的文本值。
所以当
await Task.Run(() => DisableReplication("Disable Replication"))
是 运行ning 时(调用存储过程 10 秒)它将显示Disabling Replication.
Disabling Replication..
Disabling Replication...直到该存储过程完成,然后它应该说
Disabling Replication - Complete
然后它应该调用
await Task.Run(() => ImportWeights("Importing Weights"))
,例如,proc 需要 20 秒才能完成。所以会显示Importing Weights.
Importing Weights..
Importing Weights...然后一旦完成它会说
Import Weights - Complete.
在每个方法中,都有一个布尔值在方法完成后从 false 设置为 true。该值用于 while 循环中的 ShowProgressText
方法。一旦该值设置为 true,它就会爆发。
目前它在显示 'Disabling Replication' 方面做得很好,但是一旦该方法完成,它就会开始在 'Disabling Replication' 和 'Importing Weights' 之间切换。我假设 Disabling Replication 方法已经完成,所以我不确定为什么它会继续拾取文本。我认为问题出在 ShowProgressText
方法上。
有谁知道我做错了什么,也许我能以某种方式简化它吗?
这是一个显示它正在做什么的 .gif,下面是我正在使用的代码。
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DirectMailSpendManagement
{
public partial class FrmRapport : AestheticsFormBase
{
#region Instantiations
private readonly RapportDataAccess access = new RapportDataAccess();
private readonly Panel panel = new Panel();
#endregion
#region Fields
private bool IsCompleted;
#endregion
#region Constructors
public FrmRapport()
{
InitializeComponent();
}
#endregion
#region Private Methods
private void BtnGetRapportFile(object sender, EventArgs e)
{
_ = LoadRapport();
}
private async Task LoadRapport()
{
await Task.Run(() => DisableReplication("Disable Replication"));
await Task.Run(() => ImportWeights("Importing Weights"));
}
private void DisableReplication(string txt)
{
IsCompleted = false;
Task.Run(() => ShowProgressText(txt));
access.DisableReplication();
}
private void ImportWeights(string txt)
{
IsCompleted = false;
Task.Run(() => ShowProgressText(txt));
access.ImportAndCalculateWeights(panel.PanelNumber, "", "", "");
}
private void ShowProgressText(string txt)
{
var count = 0;
var logText = new StringBuilder();
logText.Append(txt);
var baseLen = logText.Length;
while (!IsCompleted)
{
Thread.Sleep(300);
if (count >= 3)
{
logText.Remove(baseLen, count);
count = 0;
}
logText.Append(".");
count++;
BeginInvoke(new Action(() => { UpdateProgressText(logText.ToString()); }));
}
BeginInvoke(new Action(() => { UpdateProgressText(txt + " - Complete"); }));
}
private void UpdateProgressText(string txt)
{
lblProgress.Text = txt;
}
#endregion
}
}
问题是您有两个单独的任务 运行 调用 ShowProgressText。 Task.Run() 不是您通常使用的东西,除非您与不使用 C# async/await 模式的代码交互。所以也许 LoadRapport 可能是这样的:
bool IsCompleted;
string LogText;
private async Task LoadRapport()
{
LogText = "Disable Replication";
IsCompleted = false;
_ = ShowStatus(); // start this task but don't wait for it to finish.
// Start these long running methods on a separate non UI thread using Task.Run.
await Task.Run(() => DisableReplication());
LogText = "Importing Weights";
await Task.Run(() => ImportWeights());
IsCompleted = true; // tell ShowStatus to complete.
}
ShowStatus 可能是这样的:
async Task ShowStatus()
{
while (!IsCompleted) {
BeginInvoke(new Action(() =>
{
UpdateProgressText(this.LogText);
})); ;
await Task.Delay(200);
}
UpdateProgressText("Completed");
}
我还会记得在这个漫长的 运行 过程中禁用调用 BtnGetRapportFile 的按钮,这样用户就不会单击它 10 次并获得 10 个单独的线程 运行 调用您的 SQL 服务器...