{"action":"created","issue":{"url":"https://api.github.com/repos/github/VisualStudio/issues/1506","repository_url":"https://api.github.com/repos/github/VisualStudio","labels_url":"https://api.github.com/repos/github/VisualStudio/issues/1506/labels{/name}","comments_url":"https://api.github.com/repos/github/VisualStudio/issues/1506/comments","events_url":"https://api.github.com/repos/github/VisualStudio/issues/1506/events","html_url":"https://github.com/github/VisualStudio/pull/1506","id":299677646,"number":1506,"title":"Allow VSGitExt to be constructed and subscribed to from background thread","user":{"login":"jcansdale","id":11719160,"avatar_url":"https://avatars3.githubusercontent.com/u/11719160?v=4","gravatar_id":"","url":"https://api.github.com/users/jcansdale","html_url":"https://github.com/jcansdale","followers_url":"https://api.github.com/users/jcansdale/followers","following_url":"https://api.github.com/users/jcansdale/following{/other_user}","gists_url":"https://api.github.com/users/jcansdale/gists{/gist_id}","starred_url":"https://api.github.com/users/jcansdale/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jcansdale/subscriptions","organizations_url":"https://api.github.com/users/jcansdale/orgs","repos_url":"https://api.github.com/users/jcansdale/repos","events_url":"https://api.github.com/users/jcansdale/events{/privacy}","received_events_url":"https://api.github.com/users/jcansdale/received_events","type":"User","site_admin":true},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-02-23T11:12:48Z","updated_at":"2018-02-28T12:33:25Z","closed_at":"2018-02-28T12:33:25Z","author_association":"CONTRIBUTOR","pull_request":{"url":"https://api.github.com/repos/github/VisualStudio/pulls/1506","html_url":"https://github.com/github/VisualStudio/pull/1506","diff_url":"https://github.com/github/VisualStudio/pull/1506.diff","patch_url":"https://github.com/github/VisualStudio/pull/1506.patch"},"body":"This PR allows the `VSGitExt` service to be constructed and subscribed to from background thread. This is necessary to allow the package from `Show current PR on status bar` #1396 to load on a background thread (package option `AllowsBackgroundLoading = true`).\r\n\r\n#### Notes on using Task.ContinueWith to guarantee ordering of RefreshActiveRepositories\r\n\r\nI wanted to understand what I could have done to keep the ordering of `RefreshActiveRepositories` consistent when I moved it off the main thread to the thread pool. In the `VSGitExt` constructor, it was changed from `RefreshActiveRepositories()` to `Task.Run(() => RefreshActiveRepositories)`.\r\n\r\nThe body of `RefreshActiveRepositories` can be changed to use `sync`, but this doesn't guarantee the order in which tasks start executing on the thread pool. For example:\r\n\r\n```c#\r\n        async Task Lock()\r\n        {\r\n            var refreshLock = new object();\r\n            var writer = new StringWriter();\r\n            var tasks = new List<Task>();\r\n\r\n            for (int x = 0; x < 10; x++)\r\n            {\r\n                var y = x;\r\n                tasks.Add(Task.Run(() =>\r\n                {\r\n                    lock (refreshLock)\r\n                    {\r\n                        writer.Write(y + \", \");\r\n                    }\r\n                }));\r\n            }\r\n\r\n            await Task.WhenAll(tasks);\r\n            Console.WriteLine(writer);\r\n        }\r\n```\r\n\r\nMight output: `0, 3, 4, 5, 6, 7, 8, 9, 1, 2,`\r\n\r\nInterestingly the `TaskCreationOptions.PreferFairness` flag doesn't seem to make any difference when starting tasks:\r\n\r\n```c#\r\n        async Task PreferFairness()\r\n        {\r\n            var refreshLock = new object();\r\n            var writer = new StringWriter();\r\n            var tasks = new List<Task>();\r\n\r\n            for (int x = 0; x < 10; x++)\r\n            {\r\n                var y = x;\r\n                tasks.Add(Task.Factory.StartNew(() =>\r\n                {\r\n                    lock (refreshLock)\r\n                    {\r\n                        writer.Write(y + \", \");\r\n                    }\r\n                }, TaskCreationOptions.PreferFairness));\r\n            }\r\n\r\n            await Task.WhenAll(tasks);\r\n            Console.WriteLine(writer);\r\n        }\r\n```\r\n\r\nWhich outputs: `1, 3, 4, 5, 6, 7, 8, 9, 2, 0,`\r\n\r\nAn alternative approach is to use `ContinueWith`:\r\n\r\n```c#\r\n        async Task ContinueWith()\r\n        {\r\n            var writer = new StringWriter();\r\n            var task = Task.CompletedTask;\r\n\r\n            for (int x = 0; x < 10; x++)\r\n            {\r\n                var y = x;\r\n                task = task.ContinueWith(_ => writer.Write(y + \", \"), TaskScheduler.Default);\r\n            }\r\n\r\n            await task;\r\n            Console.WriteLine(writer);\r\n        }\r\n```\r\n\r\nWhich consistently outputs: `0, 1, 2, 3, 4, 5, 6, 7, 8, 9,`\r\n\r\nI prefer this approach because the intended ordering is explicit when the `ContinueWith` method is used.\r\n\r\nWhat do you think?"},"comment":{"url":"https://api.github.com/repos/github/VisualStudio/issues/comments/369225663","html_url":"https://github.com/github/VisualStudio/pull/1506#issuecomment-369225663","issue_url":"https://api.github.com/repos/github/VisualStudio/issues/1506","id":369225663,"user":{"login":"jcansdale","id":11719160,"avatar_url":"https://avatars3.githubusercontent.com/u/11719160?v=4","gravatar_id":"","url":"https://api.github.com/users/jcansdale","html_url":"https://github.com/jcansdale","followers_url":"https://api.github.com/users/jcansdale/followers","following_url":"https://api.github.com/users/jcansdale/following{/other_user}","gists_url":"https://api.github.com/users/jcansdale/gists{/gist_id}","starred_url":"https://api.github.com/users/jcansdale/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jcansdale/subscriptions","organizations_url":"https://api.github.com/users/jcansdale/orgs","repos_url":"https://api.github.com/users/jcansdale/repos","events_url":"https://api.github.com/users/jcansdale/events{/privacy}","received_events_url":"https://api.github.com/users/jcansdale/received_events","type":"User","site_admin":true},"created_at":"2018-02-28T12:33:25Z","updated_at":"2018-02-28T12:33:25Z","author_association":"CONTRIBUTOR","body":"This PR has been merged into and extended by #1510. I'll close this one and continue development there."}}
{"actor":{"display_login":"jcansdale"}}