Skip to content

Commit

Permalink
Fix threading for register for idle time (#2073)
Browse files Browse the repository at this point in the history
* Make ProjectSystem.RegisterForIdleTime threadsafe

* Better --- simpler fix
  • Loading branch information
KevinRansom authored Dec 22, 2016
1 parent 5412d30 commit eb8d0cf
Showing 1 changed file with 26 additions and 19 deletions.
45 changes: 26 additions & 19 deletions vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs
Original file line number Diff line number Diff line change
Expand Up @@ -190,23 +190,29 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem
// FSI-LINKAGE-POINT: unsited init
do Microsoft.VisualStudio.FSharp.Interactive.Hooks.fsiConsoleWindowPackageCtorUnsited (this :> Package)

let mutable mgr : IOleComponentManager = null
// Get the ComponentManager one time at the start
let mgr : IOleComponentManager = this.GetService(typeof<SOleComponentManager>) :?> IOleComponentManager

let mutable componentID = 0u

let locker = obj()
let thisLock = obj()

member this.RegisterForIdleTime() =
mgr <- this.GetService(typeof<SOleComponentManager>) :?> IOleComponentManager
if componentID = 0u && not (isNull mgr) then
let crinfo = Array.zeroCreate<OLECRINFO>(1)
let mutable crinfo0 = crinfo.[0]
crinfo0.cbSize <- Marshal.SizeOf(typeof<OLECRINFO>) |> uint32
crinfo0.grfcrf <- uint32 (_OLECRF.olecrfNeedIdleTime ||| _OLECRF.olecrfNeedPeriodicIdleTime)
crinfo0.grfcadvf <- uint32 (_OLECADVF.olecadvfModal ||| _OLECADVF.olecadvfRedrawOff ||| _OLECADVF.olecadvfWarningsOff)
crinfo0.uIdleTimeInterval <- 1000u
crinfo.[0] <- crinfo0
mgr.FRegisterComponent(this, crinfo, &componentID) |> ignore


if not (isNull mgr) && componentID = 0u then
lock (thisLock) (fun _ ->
if componentID = 0u then
let crinfo = Array.zeroCreate<OLECRINFO>(1)
let mutable crinfo0 = crinfo.[0]
crinfo0.cbSize <- Marshal.SizeOf(typeof<OLECRINFO>) |> uint32
crinfo0.grfcrf <- uint32 (_OLECRF.olecrfNeedIdleTime ||| _OLECRF.olecrfNeedPeriodicIdleTime)
crinfo0.grfcadvf <- uint32 (_OLECADVF.olecadvfModal ||| _OLECADVF.olecadvfRedrawOff ||| _OLECADVF.olecadvfWarningsOff)
crinfo0.uIdleTimeInterval <- 1000u
crinfo.[0] <- crinfo0

mgr.FRegisterComponent(this, crinfo, &componentID) |> ignore
)

/// This method loads a localized string based on the specified resource.
/// <param name="resourceName">Resource to load</param>
Expand Down Expand Up @@ -358,11 +364,12 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem
VSConstants.S_OK

override this.Dispose(disposing) =
try
lock (locker) (fun _ ->
if componentID <> 0u && not (isNull mgr) then
mgr.FRevokeComponent(componentID) |> ignore
componentID <- 0u)
try
if not (isNull mgr) && componentID <> 0u then
lock (thisLock) (fun _ ->
if componentID <> 0u then
mgr.FRevokeComponent(componentID) |> ignore
componentID <- 0u)
finally
base.Dispose(disposing)

Expand All @@ -379,7 +386,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem
override this.FDoIdle(grfidlef:uint32) =
// see e.g "C:\Program Files\Microsoft Visual Studio 2008 SDK\VisualStudioIntegration\Common\IDL\olecm.idl" for details
//Trace.Print("CurrentDirectoryDebug", (fun () -> sprintf "curdir='%s'\n" (System.IO.Directory.GetCurrentDirectory()))) // can be useful for watching how GetCurrentDirectory changes
let periodic = (grfidlef &&& (uint32 _OLEIDLEF.oleidlefPeriodic)) <> 0u
let periodic = (grfidlef &&& (uint32 _OLEIDLEF.oleidlefPeriodic)) <> 0u
if periodic && not (isNull mgr) && mgr.FContinueIdle() <> 0 then
TaskReporterIdleRegistration.DoIdle(mgr)
else
Expand Down

0 comments on commit eb8d0cf

Please sign in to comment.