- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有以下代码(https://github.com/avinash0161/OrleansExperiments/tree/c0155b4b0c8c1bfe60aea8624f2cc83a52853dc7):
// Client code
Console.WriteLine("Client making a call");
var hashGenerator = client.GetGrain<IGrainA>(0);
hashGenerator.Call_A_ToTemp();
await Task.Delay(1000);
hashGenerator.Call_B_ToTemp();
// GrainA code
public async Task Call_A_ToTemp()
{
Console.WriteLine("Making call A to a fellow grain");
IGrainB grain = this.GrainFactory.GetGrain<IGrainB>(1);
grain.CallA().ContinueWith((t)=>
{
if(t.IsFaulted)
{
// Silo message timeout is 32s so t.IsFaulted is true
Console.WriteLine("Task Faulted");
Call_A_ToTemp();
}
});
}
public async Task Call_B_ToTemp()
{
Console.WriteLine("Making call B to a fellow grain");
IGrainB grain = this.GrainFactory.GetGrain<IGrainB>(1);
await grain.CallB();
}
// GrainB code
public async Task CallA()
{
Console.WriteLine("Call A came to GrainB");
await Task.Delay(34000); // more than timeout for the caller
}
public Task CallB()
{
Console.WriteLine("Call B came to GrainB");
return Task.CompletedTask;
}
这段代码的输出是:
Client making a call
Making call A to a fellow grain
Call A came to GrainB
Making call B to a fellow grain
Task Faulted <---------------- This comes after Call_B_ToTemp executes
Making call A to a fellow grain
正如我们所见,Call_B_ToTemp 在 Call_A_ToTemp 完全执行之前执行(Call_A_ToTemp 的 ContinueWith 部分稍后执行)。这是预期的吗?它是否违反了 Cereal 的单线程性质?
当我将 Call_A_ToTemp() 中的代码替换为:
public async Task Call_A_ToTemp()
{
Console.WriteLine("Making call A to a fellow grain");
IGrainB grain = this.GrainFactory.GetGrain<IGrainB>(1);
bool isSuccess = false;
while (! isSuccess)
{
try
{
await grain.CallA();
isSuccess = true;
} catch(TimeoutException){
Console.WriteLine("task faulted");
}
}
}
代码现在保留了单线程性质,并且在执行 Call_A_ToTemp() 的所有 ContinueWith
部分之前不会调用 Call_B_ToTemp。控制台输出如下:
Client making a call
Making call A to a fellow grain
Call A came to GrainB
Task Faulted
Making call A to a fellow grain
有人能解释一下吗?当存在ContinueWith
时是否违反了单线程性质?
最佳答案
没有违反单线程的性质。您项目中的编译警告清楚地说明了问题的根源。特别是: 此异步方法缺少“await”运算符并将同步运行。考虑使用“await”运算符等待非阻塞 API 调用,或使用“await Task.Run(...)”在后台线程上执行 CPU 绑定(bind)工作。
async Task Call_A_ToTemp()
方法从不等待对 grain B 的调用。相反,它会在发出调用后立即返回。因为 Call_A_ToTemp()
返回的 Task
立即完成,所以允许在 grain 上执行另一个调用。一旦 grain.CallA()
完成,continuation (ContinueWith(...)
) 将尽快在 grain 的 TaskScheduler
上执行(例如,当 Cereal 正在等待另一个电话或闲置时)。
相反,如果等待调用或者如果 async
从方法中删除并且代码更改为返回 grain.CallA().ContinueWith(...)
调用然后将观察到预期的行为。即,将代码更改为此将为您提供预期的结果:
// removed 'async' here, since we're not awaiting anything.
// using 'async' is preferred, but this is to demonstrate a point about
// using ContinueWith and un-awaited calls
public Task Call_A_ToTemp()
{
Console.WriteLine("Making call A to a fellow grain");
IGrainB grain = this.GrainFactory.GetGrain<IGrainB>(1);
// Note the 'return' here
return grain.CallA().ContinueWith((t)=>
{
if(t.IsFaulted)
{
// Silo message timeout is 32s so t.IsFaulted is true
Console.WriteLine("Task Faulted");
Call_A_ToTemp();
}
});
}
关于c# - ContinueWith 不尊重奥尔良单线程性质,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54456369/
此处讨论的代码是用 C# 编写并使用 .netcore 3.1 执行 我有以下代码,它在后台启动工作负载而不等待它完成(即发即忘): public void StartBackgroundWork(I
我正在尝试记录对 API 的请求和响应。我目前正在使用一个 delegatingHandler 来捕获 httpwebresponses 和 httpwebrequests。 处理程序: pr
我遇到了以下我试图理解的异步代码(针对此示例进行了简化): class Program { static async Task Main(string[] args) {
我刚刚开始熟悉 Task Parallel Library,但有一个相当琐碎的问题,我无法找到明确的答案。 以下片段之间有什么区别,我应该在什么时候选择一个而不是另一个? Task t = Task.
我在一个很难重现的竞争条件下运行,从我的代码分析来看,它似乎来自一个不执行(或直到结束才执行)的延续。 这里是一些呈现上下文的伪代码: Task GetObject(string id) {
我看到了 Stephen Cleary 关于 Startnew being dangerous 的博客以及如何continuewith is also dangerous .我想在这里使用它来避免在出
我试图在这个例子中链接执行任务: static List clsTaskList = new List(); private static void Tasks2() { Task t1 =
我有以下代码(https://github.com/avinash0161/OrleansExperiments/tree/c0155b4b0c8c1bfe60aea8624f2cc83a52853d
我们的团队遇到了一个问题,即 ContinueWith() 在主机进程关闭之前不会运行。例如,下面的代码已经在生产环境中运行良好一年了。但是自从我们开始使用更新版本的框架后,我们就遇到了这个问题。 运
我在一堆 LINQ 查询上有一些 GUI。查询需要一些时间来执行,所以我希望 GUI 能够响应并显示繁忙指示器和进度条。许多查询是为了检查数据中存在的某些条件。如果查询返回空结果,应用程序应继续下一个
使用 Visual Studio 2015,针对 FW 4(在 FW 4 下测试不可观察的异常): 我期待这段代码: static void Main(string[] args) { try
如果这是一个简单的问题,请原谅我;我无法用足够通用的方式来表达它来搜索答案。 考虑这段代码: var task = Task.Factory.StartNew(() => Whatever());
使用什么值 ContinueWith(Action continuationAction)对于 CancellationToken , TaskContinuationOptions和 TaskSch
我有这个示例代码: static void Main(string[] args) { var t1 = Task.Run(async () => {
我有一些代码用作轻量级、非阻塞的关键部分。我希望无论 Task.Run 子句中的 _func 和 cancellationToken 发生什么情况,都能保证继续运行,这样finally block 中
我用这个代码 public static void Main() { Task t = new Task(() => { return 43; });
请看下面的代码- static void Main(string[] args) { // Get the task. var task = Task.Factory.StartNew
我有控制台应用程序和代码如下, 我的问题是在ContinueWith任务完成之前,控制台应用程序结束,它不等待continueWith完成,请指教。 请让我知道我遗漏了什么或不正确。 var task
我有以下代码,其中延续代码没有被执行。 using System; using System.Threading; using System.Threading.Tasks; namespace Ko
据我了解,ContinueWith 方法会等待相关任务完成。对于以下代码,这意味着它在完成子任务后就完成了。如果这是真的,为什么它有时会输出0 0 0 和其他时间 0 1 2? static
我是一名优秀的程序员,十分优秀!