Захватывает ли лямбда самый внешний экземпляр?C#

Место общения программистов C#
Ответить
Anonymous
 Захватывает ли лямбда самый внешний экземпляр?

Сообщение Anonymous »


Когда я раскомментирую await Task.Delay(1_000);, foo.DoAsync внутри Task.Run — это Task.CompletedTask, потому что он ожидает служебных данных Task.Run. Поэтому он работает нормально.
Когда я комментирую await Task.Delay(1_000);, foo.DoAsync внутри Task.Run — это сам собой. После первого попадания в точку останова2 в режиме отладки точка останова2 больше не попадает.
internal class Foo
{
public Task DoAsync { get; set; }

public void Recursive()
{
// Breakpoint1
Recursive();
}
}

var foo = new Foo() { DoAsync = Task.CompletedTask };

//foo.Recursive();

Console.WriteLine($"Outer ThreadId: {Environment.CurrentManagedThreadId}");

var task = Task.Run(async () =>
{
Console.WriteLine($"Inner ThreadId: {Environment.CurrentManagedThreadId}");
// Breakpoint2
await foo.DoAsync;
Console.WriteLine("""
******
******
******
done
******
******
******
""");
});

await Task.Delay(1_000);

foo.DoAsync = task;

await foo.DoAsync;

Я ожидал, что он будет бесконечно достигать точки останова 2, поскольку foo.Recursive будет бесконечно достигать точки останова 1, пока не произойдет сбой. Куда направляется поток управления после первоначального попадания в точку останова 2?

Извините за путаницу.

Когда мне нужно что-то сделать test Я просто пишу foo, bar, baz, комментирую по завершении

, пишу новый foo, копирую какой-то метод из предыдущего и так далее.
Я лечил foo.DoAsync как Func хотя сейчас это Task.

Поэтому, когда мои глаза увидели await foo.DoAsync,

мой мозг интерпретировал это как await foo.DoAsync()< /code>
Могу ли я задать еще один вопрос, если можно.

Захватывает ли лямбда самый внешний экземпляр?

Спасибо за предыдущий ответьте, кстати.
public static async Task ActualAsync()
{
var foo = new Foo();

Console.WriteLine("************** Actual begin **************");

var task = Task.Run(async () =>
{
// Causes a deadlock because lambda didn't caputer the foo.ATask before it's overwritten.
Console.WriteLine($"a: {await foo.ATask} expecting 1");
Console.WriteLine($"b: {await foo.BTask} expecting 2");
return 3;
});

// Give time to Task.Run so it can run before foo.ATask is overwritten.
//await Task.Delay(1000);

foo.ATask = task;

await foo.ATask;

Console.WriteLine("************** Actual end **************");
}

internal class Foo
{
public Task ATask = Task.FromResult(1);
public Task BTask = Task.FromResult(2);
}

Я думал, что лямбда будет захватывать переменные отдельно.
public static async Task ExpectedAsync()
{
var foo = new Foo();

var lambdaInstance = new FooLambdaExpected()
{
ATask = foo.ATask,
BTask = foo.BTask
};

Console.WriteLine("************** Expected begin ************");

var task = Task.Run(lambdaInstance.LambdaMethod);

foo.ATask = task;

await foo.ATask;

Console.WriteLine("************** Expected end ************");
}

internal class FooLambdaExpected
{
public Task ATask { get; set; } = null!;
public Task BTask { get; set; } = null!;

public async Task LambdaMethod()
{
Console.WriteLine($"a: {await ATask} expecting 1");
Console.WriteLine($"b: {await BTask} expecting 2");
return 3;
}
}

и я думаю, он сам ловит foo.
public static async Task AssumedAsync()
{
var foo = new Foo();

var lambdaInstance = new FooLambdaAssumed()
{
Foo = foo
};

Console.WriteLine("************** Assumed begin ***********");

var task = Task.Run(lambdaInstance.LambdaMethod);

// Give time to Task.Run so it can run before foo.ATask is overwritten.
//await Task.Delay(1000);

foo.ATask = task;

await foo.ATask;

Console.WriteLine("************** Assumed end ***********");
}

internal class FooLambdaAssumed
{
public Foo Foo { get; set; } = null!;

public async Task LambdaMethod()
{
Console.WriteLine($"a: {await Foo.ATask} expecting 1");
Console.WriteLine($"b: {await Foo.BTask} expecting 2");
return 3;
}
}


Подробнее здесь: https://stackoverflow.com/questions/792 ... t-instance
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»