SWIFT TASK CONTINUATION MISUSE: leaked its continuation
Your guard is capturing a case and not calling the continuation. You need to call the continuation (e.g. continuation.resume(...)
) from all branches so that it is not leaked.
This early return
is causing the issue
guard case let .failure(error) = response.result else { return }
In your example you would need to decide how to handle response.data
being nil and response.result
being success and then update your guard
to invoke continuation.resume(...)
appropriately.
Swift: using combination of Combine and async/await results in Fatal error: SWIFT TASK CONTINUATION MISUSE tried to resume its continuation
A continuation must be resumed exactly once. You are retaining the continuation in the sink closure, and you have a constant publisher value, so the second time you hit the button, a new sink operation is created and the publisher is now sending its results to two continuations. You need to make the sink operation happen once only by unsubscribing it when it's done, or by nullifying a local reference to the continuation in the sink (untested example below):
let autocompletedComponents = await withCheckedContinuation { continuation in
var oneShot = Optional(continuation)
publisher
.sink {
oneShot?.resume(returning: $0)
oneShot = nil
}
.store(in: &cancellables)
}
However, apart from learning purposes it's not clear what benefits you're adding by mixing Combine and structured concurrency in this example. Given that the nature of the local search completer is to deliver a continuously updating set of values as the user types, Combine seems like a better fit here. You could wrap the delegate calls with a continuation but you'd have the same problem, you must resume the continuation once and only once which probably means creating brand new delegates for each request.
Pending Task in Swift
You don't need to use Task
to do this. You can use withCheckedThrowingContinuation
to convert the method f
into an async throws
method. Then when you call it, a child task of the current task is automatically created and you can await
it directly.
class A: NSObject, CLLocationManagerDelegate {
let locationManager = CLLocationManager()
var continuation: CheckedContinuation<CLLocation, Error>?
func f() async throws -> CLLocation {
try await withCheckedThrowingContinuation { continuation in
self.continuation = continuation
locationManager.delegate = self
locationManager.requestLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
continuation?.resume(returning: locations[0])
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
continuation?.resume(throwing: error)
}
}
Your B.f
method can also be rewritten as an async
method (I don't know what cauterize
does):
class B {
let a = A()
func f() async {
do {
print(try await a.f())
} catch {
print(error)
}
}
}
let b = B()
_runAsyncMain { // so that we have an async context to await tasks
await b.f()
}
Side note: if you actually run this, you will get an error printed from the catch block, probably because location manager needs permission :)
Async/Await function without a return | Swift 5.5
This is what worked the best:
try await withUnsafeThrowingContinuation { (continuation: UnsafeContinuation<Void, Error>) in
Composing Task.async_stream vs. Continuation passing
If both functions are IO bound, then there shouldn't be any problem with your first example:
enum
|> Task.async_stream(Mod1, :func1, [])
|> Task.async_stream(Mod2, :func2, [])
If you did want to collapse the two calls, I wouldn't use a continuation style, just pipeline them in a lambda passed to Task.async_stream/3:
enum
|> Task.async_stream(fn x -> x |> Mod1.func1() |> M2.func2() end)
Alternatively, you might consider using Flow:
enum
|> Flow.from_enumerable()
|> Flow.map(&Mod1.func1/1)
|> Flow.map(&Mod2.func2/1)
|> Flow.run()
Async in Task ContinueWith behavior?
The code below is equivalent to your example, with variables explicitly declared, so that it's easier to see what's going on:
Task task = Task.Run(() => { });
Task<Task> continuation1 = task.ContinueWith(async prev =>
{
Console.WriteLine("Continue with 1 start");
await Task.Delay(1000);
Console.WriteLine("Continue with 1 end");
});
Task continuation2 = continuation1.ContinueWith(prev =>
{
Console.WriteLine("Continue with 2 start");
});
await continuation2;
Console.WriteLine($"task.IsCompleted: {task.IsCompleted}");
Console.WriteLine($"continuation1.IsCompleted: {continuation1.IsCompleted}");
Console.WriteLine($"continuation2.IsCompleted: {continuation2.IsCompleted}");
Console.WriteLine($"continuation1.Unwrap().IsCompleted:" +
$" {continuation1.Unwrap().IsCompleted}");
await await continuation1;
Output:
Continue with 1 start
Continue with 2 start
task.IsCompleted: True
continuation1.IsCompleted: True
continuation2.IsCompleted: True
continuation1.Unwrap().IsCompleted: False
Continue with 1 end
The tricky part is the variable continuation1
, that is of type Task<Task>
. The ContinueWith
method does not unwrap automatically the Task<Task>
return values like Task.Run
does, so you end up with these nested tasks-of-tasks. The outer Task
's job is just to create the inner Task
. When the inner Task
has been created (not completed!), then the outer Task
has been completed. This is why the continuation2
is completed before the inner Task
of the continuation1
.
There is a built-in extension method Unwrap
that makes it easy to unwrap a Task<Task>
. An unwrapped Task
is completed when both the outer and the inner tasks are completed. An alternative way to unwrap a Task<Task>
is to use the await
operator twice: await await
.
Castle Windsor equivalent of StructureMap ObjectFactory.With ().GetInstance ()
You can register an instance as the implementation of a given component like this:
container.Register(Component
.For<ISomeDependency>()
.Instance(someDependencyInstance));
This means that everytime you resolve anything and ISomeDependency is part of the resolved object graph, the someDependencyInstance
instance will be used.
It that what you want, or did I misunderstand the question?
Based on additional information, here's a new attempt at answering the question.
You should be able to use container hierarchies for this. If a Windsor container can't resolve a type, it'll ask its parent. This means that you can create a child container that contains only the override and then ask that container to resolve the type for you.
Here's an example:
var container = new WindsorContainer();
container.Register(Component
.For<ISomeDependency>()
.ImplementedBy<SomeDependency>());
container.Register(Component
.For<IService>()
.ImplementedBy<Service>());
var childContainer = new WindsorContainer();
childContainer.Register(Component
.For<ISomeDependency>()
.ImplementedBy<SomeOtherDependency>());
childContainer.Parent = container;
var service = childContainer.Resolve<IService>();
The resolved service
will contain an instance of SomeOtherDependency and not SomeDependency.
Notice how childContainer
only overrides the registration of ISomeDependency. All other registrations are used from the parent.
Related Topics
Show Nsmenu Only on Nsstatusbarbutton Right Click
How to Implement iOServicematchingcallback in Swift
How to Speed Up Updating Relationship Among Tables, After One or Both Tables Are Already Saved
Animating a Navigation Bar Color
How to Set an Environment Object in Preview
Label Disappear When Changing Font Size to 25 in Swift
Error: Binary Operator '<=' Cannot Be Applied to Operands of Type 'Int' and 'Int'
How to Dismiss a Uisearchcontroller? (iOS 8 and Follow)
How to Generate Random Numbers Without Repetition in Swift
Session.Datataskwithurl Completionhandler Never Called
Pickers Are Overlapping in iOS 15 Preventing Some of Them to Be Scrolled
Cannot Invoke 'Filter' with an Argument List of Type '((_) -> _)'
Pattern Match and Conditionally Bind in a Single Switch Statement
What's the Best Way to Cut Swift String into 2-Letter-Strings