public PythonDebugProcessReplEvaluator(IServiceProvider serviceProvider, PythonProcess process, IThreadIdMapper threadIdMapper) : base(serviceProvider) { _process = process; _threadIdMapper = threadIdMapper; _threadId = process.GetThreads()[0].Id; _languageVersion = process.LanguageVersion; _currentScopeName = CurrentFrameScopeFixedName; DisplayName = Strings.DebugReplDisplayName; }
public PythonDebugProcessReplEvaluator(IServiceProvider serviceProvider, PythonProcess process, PythonToolsService pyService, IThreadIdMapper threadIdMapper) : base(serviceProvider, pyService, GetOptions(serviceProvider, pyService)) { _process = process; _threadIdMapper = threadIdMapper; _threadId = process.GetThreads()[0].Id; _languageVersion = process.LanguageVersion; EnsureConnected(); }
public PythonDebugProcessReplEvaluator(IServiceProvider serviceProvider, PythonProcess process, IThreadIdMapper threadIdMapper) : base(serviceProvider) { _process = process; _threadIdMapper = threadIdMapper; _threadId = process.GetThreads()[0].Id; _languageVersion = process.LanguageVersion; DisplayName = "Debug"; EnsureConnectedOnCreate(); }
internal void AttachProcess(PythonProcess process, IThreadIdMapper threadIdMapper) { if (_evaluators.ContainsKey(process.Id)) { // Process is already attached, so just switch to it if needed SwitchProcess(process, false); return; } process.ProcessExited += new EventHandler <ProcessExitedEventArgs>(OnProcessExited); var evaluator = new PythonDebugProcessReplEvaluator(_serviceProvider, process, _pyService, threadIdMapper); evaluator.Window = _window; evaluator.AvailableScopesChanged += new EventHandler <EventArgs>(evaluator_AvailableScopesChanged); evaluator.MultipleScopeSupportChanged += new EventHandler <EventArgs>(evaluator_MultipleScopeSupportChanged); _evaluators.Add(process.Id, evaluator); _activeEvaluator = evaluator; }
internal async Task AttachProcessAsync(PythonProcess process, IThreadIdMapper threadIdMapper) { _serviceProvider.GetUIThread().MustBeCalledFromUIThread(); if (_evaluators.ContainsKey(process.Id)) { // Process is already attached, so just switch to it if needed SwitchProcess(process, false); return; } process.ProcessExited += new EventHandler <ProcessExitedEventArgs>(OnProcessExited); var evaluator = new PythonDebugProcessReplEvaluator(_serviceProvider, process, threadIdMapper); evaluator.CurrentWindow = CurrentWindow; await evaluator.InitializeAsync(); evaluator.AvailableScopesChanged += new EventHandler <EventArgs>(evaluator_AvailableScopesChanged); evaluator.MultipleScopeSupportChanged += new EventHandler <EventArgs>(evaluator_MultipleScopeSupportChanged); _evaluators.Add(process.Id, evaluator); _activeEvaluator = evaluator; }
internal async Task AttachProcessAsync(PythonProcess process, IThreadIdMapper threadIdMapper) { // The fact that this is only called from UI thread is no guarantee // that there won't be more than one "instance" of this method in // progress at any time (though only one is executing while others are paused). // It's possible because this is an async method with await(s), and // UI thread execution will temporarily continue somewhere else when // await is used, and that somewhere else can be code that calls // into this method with the same process id! // The more relevant trigger for this cooperative multitasking is // the await on evaluator.InitializeAsync, and when that happens // the evaluator is not in the _evaluators dictionary yet. // If a second caller comes in (on the same UI thread) during that // await, it gets past the first check because it's not in _evaluators, // and then checks the _attachingTasks dictionary and know to wait // for that instead of creating a new evaluator. // Note that adding the uninitialized evaluator to the _evaluators // dictionary would be a potentially bug prone solution, as other // code may try to use it before it's fully initialized. _serviceProvider.GetUIThread().MustBeCalledFromUIThread(); if (_evaluators.ContainsKey(process.Id)) { // Process is already attached, so just switch to it if needed SwitchProcess(process, false); return; } // Keep track of evaluators that are in progress of attaching, and if // we are getting called to attach for one that is already in progress, // just wait for it to finish before returning. // Important: dictionary must be checked (and updated) before any // await call to avoid race condition. Task attachingTask; TaskCompletionSource <object> attachingTcs = null; if (_attachingTasks.TryGetValue(process.Id, out attachingTask)) { await attachingTask; return; } else { attachingTcs = new TaskCompletionSource <object>(); _attachingTasks.Add(process.Id, attachingTcs.Task); } process.ProcessExited += new EventHandler <ProcessExitedEventArgs>(OnProcessExited); var evaluator = new PythonDebugProcessReplEvaluator(_serviceProvider, process, threadIdMapper) { CurrentWindow = CurrentWindow }; evaluator.AvailableScopesChanged += new EventHandler <EventArgs>(evaluator_AvailableScopesChanged); evaluator.MultipleScopeSupportChanged += new EventHandler <EventArgs>(evaluator_MultipleScopeSupportChanged); await evaluator.InitializeAsync(); _evaluators.Add(process.Id, evaluator); _activeEvaluator = evaluator; // Only refresh available scopes after the active evaluator has // been changed, because that's where the UI will look. await evaluator.RefreshAvailableScopes(); attachingTcs.SetResult(null); _attachingTasks.Remove(process.Id); }
internal void AttachProcess(PythonProcess process, IThreadIdMapper threadIdMapper) { if (_evaluators.ContainsKey(process.Id)) { // Process is already attached, so just switch to it if needed SwitchProcess(process, false); return; } process.ProcessExited += new EventHandler<ProcessExitedEventArgs>(OnProcessExited); var evaluator = new PythonDebugProcessReplEvaluator(_serviceProvider, process, _pyService, threadIdMapper); evaluator.Window = _window; evaluator.InitializeAsync().WaitAndUnwrapExceptions(); evaluator.AvailableScopesChanged += new EventHandler<EventArgs>(evaluator_AvailableScopesChanged); evaluator.MultipleScopeSupportChanged += new EventHandler<EventArgs>(evaluator_MultipleScopeSupportChanged); _evaluators.Add(process.Id, evaluator); _activeEvaluator = evaluator; }