{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/coreclr/issues/16307","repository_url":"https://api.github.com/repos/dotnet/coreclr","labels_url":"https://api.github.com/repos/dotnet/coreclr/issues/16307/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/coreclr/issues/16307/comments","events_url":"https://api.github.com/repos/dotnet/coreclr/issues/16307/events","html_url":"https://github.com/dotnet/coreclr/issues/16307","id":295998149,"number":16307,"title":"ExecutionContext.SuppressFlow() suppression state does not flow","user":{"login":"TimLovellSmith","id":2711795,"avatar_url":"https://avatars0.githubusercontent.com/u/2711795?v=4","gravatar_id":"","url":"https://api.github.com/users/TimLovellSmith","html_url":"https://github.com/TimLovellSmith","followers_url":"https://api.github.com/users/TimLovellSmith/followers","following_url":"https://api.github.com/users/TimLovellSmith/following{/other_user}","gists_url":"https://api.github.com/users/TimLovellSmith/gists{/gist_id}","starred_url":"https://api.github.com/users/TimLovellSmith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TimLovellSmith/subscriptions","organizations_url":"https://api.github.com/users/TimLovellSmith/orgs","repos_url":"https://api.github.com/users/TimLovellSmith/repos","events_url":"https://api.github.com/users/TimLovellSmith/events{/privacy}","received_events_url":"https://api.github.com/users/TimLovellSmith/received_events","type":"User","site_admin":false},"labels":[{"id":517097440,"url":"https://api.github.com/repos/dotnet/coreclr/labels/area-System.Threading","name":"area-System.Threading","color":"d4c5f9","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-02-09T20:14:35Z","updated_at":"2018-02-09T21:47:26Z","closed_at":null,"author_association":"NONE","body":"Hi,\r\nI have been wrestling with behavior of ExecutionContext.SuppressFlow() when combined with await/async. I have slowly come to believe the current behavior (in .net version I'm using at least) is flawed. Here is the problem.\r\n\r\nBecause ExecutionContext does not come for free, and saving/restoring it has measurable overheads,\r\nI think it is a good idea for me to suppress the ExecutionContext flow in a method I have which loops for a long time and happens to be implemented as async. I.e. something like this\r\n\r\n```\r\nasync void ReadWriteLoop()\r\n{\r\n    ExecutionContext.SuppressFlow();\r\n    while (true)\r\n    {\r\n         await AsyncCallNumberOne();\r\n         await AsyncCallNumberTwo();\r\n         await AsyncCallNumberThree();\r\n    }\r\n}\r\n\r\nasync Task AsyncCallNumberOne()\r\n{\r\n    await AsyncCallNumberFour();\r\n    await AsyncCallNumberFive();\r\n}\r\n```\r\n\r\nHowever, the observed behavior of this code is that after each async call, `ExecutionContext.IsFlowSuppressed()` might return `false`.\r\nThis presents a problem. The only way I can definitely get ExecutionContext to be suppressed for this entire logical execution flow is by peppering suppress calls everywhere:\r\n\r\n```\r\nvoid EnsureSuppressed() { If (!ExecutionContext.IsFlowSuppressed()) ExecutionContext.SuppressFlow(); }\r\n\r\nasync void ReadWriteLoop()\r\n{\r\n    while (true)\r\n    {\r\n         EnsureSuppressed();\r\n         await AsyncCallNumberOne();\r\n         EnsureSuppressed();\r\n         await AsyncCallNumberTwo();\r\n         EnsureSuppressed();\r\n         await AsyncCallNumberThree();\r\n    }\r\n}\r\n\r\nasync Task AsyncCallNumberOne()\r\n{\r\n    Debug.Assert(ExecutionContext.IsFlowSuppressed(), \"we know it is suppressed by the caller... in this case\");\r\n    await AsyncCallNumberFour();\r\n    EnsureSuppressed();\r\n    await AsyncCallNumberFive();\r\n}\r\n```\r\nI.e. the observed behavior is that while the _execution context_ successfully is suppressed, and we resume execution without restoring the execution context, the _suppression state_  is not restored, requiring us to suppress execution context all over again in order to get it really suppressed.\r\n\r\nThis doesn't seem good. Calling ExecutionConext.IsFlowSuppressed() and ExecutionContext.SuppressFlow() like this isn't free in either lines of code nor CPU and memory!\r\n\r\nThe behavior I actually believe should happen is that the _suppression state_ should be preserved around the async call, meaning there need be no further calls to EnsureSuppressed();\r\n\r\nThat would better fulfil what I believe the _intent_ of ExecutionContext.SuppressFlow() is: to suppress flow of the entire context for the current 'logical execution operation'.\r\n\r\nAnd then it also might be feasible to undo the suppression correctly (currently it seems like it is a conceptual mess to do this!)"},"comment":{"url":"https://api.github.com/repos/dotnet/coreclr/issues/comments/364578504","html_url":"https://github.com/dotnet/coreclr/issues/16307#issuecomment-364578504","issue_url":"https://api.github.com/repos/dotnet/coreclr/issues/16307","id":364578504,"user":{"login":"RussKeldorph","id":15160879,"avatar_url":"https://avatars3.githubusercontent.com/u/15160879?v=4","gravatar_id":"","url":"https://api.github.com/users/RussKeldorph","html_url":"https://github.com/RussKeldorph","followers_url":"https://api.github.com/users/RussKeldorph/followers","following_url":"https://api.github.com/users/RussKeldorph/following{/other_user}","gists_url":"https://api.github.com/users/RussKeldorph/gists{/gist_id}","starred_url":"https://api.github.com/users/RussKeldorph/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RussKeldorph/subscriptions","organizations_url":"https://api.github.com/users/RussKeldorph/orgs","repos_url":"https://api.github.com/users/RussKeldorph/repos","events_url":"https://api.github.com/users/RussKeldorph/events{/privacy}","received_events_url":"https://api.github.com/users/RussKeldorph/received_events","type":"User","site_admin":false},"created_at":"2018-02-09T21:47:26Z","updated_at":"2018-02-09T21:47:26Z","author_association":"MEMBER","body":"@kouvel @stephentoub "}}
{"actor":{"display_login":"RussKeldorph"}}