Calling Task-based methods from ASMX

前端 未结 2 976
感情败类
感情败类 2020-12-28 19:09

I have a recent experience I\'d like to share that may be helpful to anyone having to maintain a legacy ASMX web service that must be updated to call Task-based methods.

2条回答
  •  鱼传尺愫
    2020-12-28 19:52

    Upon further investigation, I discovered that sub-tasks created by the initial task could be awaited without any problems, but the parent task (i.e. the method call in the ASMX that returned a Task) was never detected as completing.

    The investigation led me to theorise that there was some sort of incompatibility between the legacy Web Services stack and the Task Parallel Library. The solution that I came up with involves creating a new thread to run the Task-based method calls, the idea being that a separate thread would not be subject to thread/task management incompatibilities that existed in the thread processing the ASMX request. To this end I created a simple helper class that will run a Func in a new thread, block the current thread until the new thread terminates and then returns the result of the function call:

    public class ThreadRunner {
        // The function result
        private T result;
    
        //The function to run.
        private readonly Func function;
    
        // Sync lock.
        private readonly object _lock = new object();
    
    
        // Creates a new ThreadRunner.
        public ThreadRunner(Func function) {
            if (function == null) {
                throw new ArgumentException("Function cannot be null.", "function");
            }
    
            this.function = function;
        }
    
    
        // Runs the ThreadRunner's function on a new thread and returns the result.
        public T Run() {
            lock (_lock) {
                var thread = new Thread(() => {
                    result = function();
                });
    
                thread.Start();
                thread.Join();
    
                return result;
            }
        }
    }
    
    // Example:
    //
    // Task MyTaskBasedMethod() { ... }
    //
    // ...
    //
    // var tr = new ThreadRunner(() => MyTaskBasedMethod().Result);
    // return tr.Run();
    

    Running the Task-based method in this way works perfectly and allows the ASMX call to complete successfully, but it's obviously a bit brute-force to spawn a new thread for every asynchronous call; alternatives, improvements or suggestions are welcome!

提交回复
热议问题