gpt4 book ai didi

c# - 为什么任务在执行下一个代码之前等待Task.Run而不是Task.Factory.StartNew?

转载 作者:行者123 更新时间:2023-12-02 16:16:33 25 4
gpt4 key购买 nike

至少当我在代码中实现它时,我必须修改 StartNew Task 才能获得相同的行为。在我的 View 中有一个开始按钮。它的 IsEnabled 属性绑定(bind)到 View 模型中的 bool 值。如果不添加 await task.ContinueWith(_ => true); 并将 return true; 移出 try block ,PopulateListStartNew Task 不会等待,因此按钮保持启用状态。我更喜欢使用 Task.Factory.StartNew 因为传递 TaskScheduler 可以使代码更具可读性(没有 Dispatcher 困惑)。 Records 是一个 ObservableCollection。

我认为 Task.Run 基本上是一个快捷方式(根据 Task.Run vs Task.Factory.StartNew 。无论如何,我想更好地理解行为上的差异,并且肯定会感谢任何与使我的示例代码更好相关的建议。

public async Task<bool> PopulateListTaskRun(CancellationToken cancellationToken)
{
try
{
await Task.Run(async () =>
{
// Clear the records out first, if any
Application.Current.Dispatcher.InvokeAsync(() => Records.Clear());


for (var i = 0; i < 10; i++)
{
if (cancellationToken.IsCancellationRequested)
{
return;
}

// Resharper says do this to avoid "Access to modified closure"
var i1 = i;

Application.Current.Dispatcher.InvokeAsync(() =>
{
Records.Add(new Model
{
Name = NamesList[i1],
Number = i1
});

Status = "cur: " +
i1.ToString(
CultureInfo.InvariantCulture);
});

// Artificial delay so we can see what's going on
await Task.Delay(200);
}

Records[0].Name = "Yes!";
}, cancellationToken);

return true;
}
catch (Exception)
{
return false;
}
}

public async Task<bool> PopulateListStartNew(CancellationToken cancellationToken, TaskScheduler taskScheduler)
{
try
{
var task = await Task.Factory.StartNew(async () =>
{
// Clear the records out first, if any
Records.Clear();


for (var i = 0; i < 10; i++)
{
if (cancellationToken.IsCancellationRequested)
{
return;
}

Records.Add(new Model
{
Name = NamesList[i],
Number = i
});

Status = "cur: " +
i.ToString(
CultureInfo.InvariantCulture);


// Artificial delay so we can see what's going on
await Task.Delay(200);
}

Records[0].Name = "Yes!";
}, cancellationToken, TaskCreationOptions.None, taskScheduler);

// Had to add this
await task.ContinueWith(_ => true);
}
catch (Exception)
{
return false;
}

// Had to move this out of try block
return true;
}

最佳答案

您在问题中发布的链接有答案:Task.Run理解并打开 async Task代表们,同时StartNew返回 Task<Task>相反,您必须通过调用 Unwrap 自行解开包装。或者做一个双await .

但是,我建议您完全重写代码,如下所示。备注:

  • 请勿使用Dispatcher 。正确编写的 async 应该不需要它。代码。
  • 将所有后台工作方法和异步操作视为 UI 线程的“服务”。因此,您的方法将根据需要定期返回 UI 上下文。

像这样:

public async Task<bool> PopulateListTaskRunAsync(CancellationToken cancellationToken)
{
try
{
// Clear the records out first, if any
Records.Clear();

for (var i = 0; i < 10; i++)
{
cancellationToken.ThrowIfCancellationRequested();

Records.Add(new Model
{
Name = NamesList[i],
Number = i
});

Status = "cur: " + i.ToString(CultureInfo.InvariantCulture);

// Artificial delay so we can see what's going on
await Task.Delay(200);
}

Records[0].Name = "Yes!";
return true;
}
catch (Exception)
{
return false;
}
}

关于c# - 为什么任务在执行下一个代码之前等待Task.Run而不是Task.Factory.StartNew?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17202314/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com