Change:
public run(task: Task, resolver: ITaskResolver, trigger: string = Triggers.command): ITaskExecuteResult { task = task.clone(); // A small amount of task state is stored in the task (instance) and tasks passed in to run may have that set already. <del> const recentTaskKey = task.getRecentlyUsedKey() ?? ''; const validInstance = !this._instances[recentTaskKey] || this._instances[recentTaskKey].instances < ((task.runOptions && task.runOptions.instanceLimit) ?? 0); const instance = this._instances[recentTaskKey] ? this._instances[recentTaskKey].instances : 0; </del> <ins> const instances = InMemoryTask.is(task) || this._isTaskEmpty(task) ? [] : this._getInstances(task); const validInstance = instances.length < ((task.runOptions && task.runOptions.instanceLimit) ?? 1); const instance = instances[0]?.count?.count ?? 0; </ins> this._currentTask = new VerifiedTask(task, resolver, trigger); if (instance > 0) { <del> task.instance = this._instances[recentTaskKey].counter; </del> <ins> task.instance = instance; </ins> } <del> const lastTaskInstance = this.getLastInstance(task); const terminalData = lastTaskInstance ? this._activeTasks[lastTaskInstance.getMapKey()] : undefined; </del> if (!validInstance) { <del> if (terminalData && terminalData.promise) { this._lastTask = this._currentTask; return { kind: TaskExecuteKind.Active, task: terminalData.task, active: { same: true, background: task.configurationProperties.isBackground! }, promise: terminalData.promise }; } throw new TaskError(Severity.Warning, nls.localize('TaskSystem.active', 'There is already a task running. Terminate it first before executing another task.'), TaskErrors.RunningTask); </del> <ins> const terminalData = instances[instances.length - 1]; this._lastTask = this._currentTask; return { kind: TaskExecuteKind.Active, task: terminalData.task, active: { same: true, background: task.configurationProperties.isBackground! }, promise: terminalData.promise }; </ins> } try {

Discussion:
<!-- Do Not Delete This! bugreporttemplate --<!-- Please read our Rules of Conduct: --<!-- Read our guide about submitting issues: --<!-- Search existing issues to avoid creating duplicates. --<!-- Test using the latest Insiders build to see if your issue has already been fixed: --<!-- Instead of creating your report here, use 'Report Issue' from the 'Help' menu in VS Code to pre-fill useful information. --<!-- Launch with to check. --Does this issue occur when all extensions are disabled?: Yes <!-- If you answered No above, use 'Help: Start Extension Bisect' from Command Palette to try to identify the cause. --<!-- Issues caused by an extension need to be reported directly to the extension publisher. The 'Help Report Issue' dialog can assist with this. --- VS Code Version: 1.78.0 and older and (with slightly different behavior) insiders as of 5/4/2023 OS Version: MacOS 13.3.1 (a) Steps to Reproduce: Use these commands to produce and launch a suitable project: First bug: in either 1.78.0 or the nightly, use to launch , then hit Cmd-Shift-B to launch . You end up with two copies of running, when it should have an implicit of 1. Hit Cmd-Shift-B again, and it will tell you you've hit the instance limit. The problem here is that dependent tasks don't count towards the instance limit. Second bug: Now add to , and repeat the above. There is no change in the nightly (as you might expect), but surprisingly 1.78.0 now reports that it can't start a second copy. But thats just a bug; if you change it to and repeat, 1.78.0, still tells you it can't launch a second copy. This bug was fixed by , so I'm just including it for completeness. Third bug: Add to . Now hit Cmd-Shift-B to launch , then use to launch . will (correctly) re-use the already running task, rather than launching a new one. Now kill all the terminals (to make the next step less confusing). Hit Cmd-Shift-B to launch sleeper, wait 5 seconds, and hit Cmd-Shift-B again, wait another 5 seconds for the first task to finish, and then run .

Now, although the second task is still running, starts a new one. The issue here is that when looking for an existing dependent task, uses the task's , which only matches the first instance of a task with greater than 1 (and here, that task has already finished).