Hi Team,
I am working on Excel-DNA with F#.
I am having the same issue in the following posts
The main problem is that the following FsAsync.FsAsyncUtil.excelObserve function will run in the thread pool. It crashes if too many cells are executing this function.
Here is the code
// to create a Timer
let createTimer (interval: float) =
let timer = new System.Timers.Timer(interval)
timer.AutoReset <- true
timer.Start()
timer.Elapsed
// helper function to use with excelObserve
let performOnEvent event (f: unit -> 'b) : IObservable<'b>=
event
|> Observable.map (fun _ -> f ())
// test function
let testAsync =
async {
let res = rnd.Next(0,1000)
return res
}
let funTest () =
Async.RunSynchronously testAsync
// example
[<ExcelFunction(Description = "Test")>]
let testObservable (str: string) =
FsAsync.FsAsyncUtil.excelObserve "test" [|str|]
(performOnEvent (createTimer 5000.) funTest)
I then tried to use Async.StartWithContinuations (adding timer in the async function to force it refresh) as below
let excelRunAsync functionName parameters async =
let obsSource =
ExcelObservableSource(
fun () ->
{ new IExcelObservable with
member __.Subscribe observer =
// make something like CancellationDisposable
let cts = new CancellationTokenSource ()
let disp = { new IDisposable with member __.Dispose () = cts.Cancel () }
// Start the async computation on this thread
Async.StartWithContinuations
( async,
( fun result ->
observer.OnNext(result)
observer.OnCompleted () ),
( fun ex -> observer.OnError ex ),
( fun ex ->
observer.OnCompleted () ),
cts.Token
)
// return the disposable
disp
})
ExcelAsyncUtil.Observe (functionName, parameters, obsSource)
// test function 2
let testAsync2 (timer) =
async {
let res = rnd.Next(0,1000)
return res
}
// Timer()
let Timer () =
FsAsync.FsAsyncUtil.excelObserve "Timer" [||]
(performOnEvent (createTimer 5000.) (fun _ -> some random number))
// example
[<ExcelFunction(Description = "Test 2")>]
let testObservable2 () =
FsAsync.FsAsyncUtil.excelRunAsync “test 2” [|Timer()|] (testAsync2(Timer()))
It works well with multiple cells this time. However, these cells will show #N/A in excel while pending the corresponding Async function to return a value. I want to keep the previous value in excel while the Async function is computing, so other cells may use this current values before a new values.
I am thinking to solve these problems by two approaches,
1. A way to merge the following functions “excelRunAsync” and “excelObserve” into one single function so that it won’t give #N/A while pending Async computation.
2. A way to store the previous result and keep it while pending Async computation.
May I ask if the above approaches are possible?
Many thanks
Mark