如何在C#中延迟方法调用?

时间:2022-01-14 04:15:39

Is there a way to schedule a method call, when current processing of user input is finished? Something like posting an user message to the message queue.

当用户输入的当前处理完成时,有没有办法安排方法调用?比如将用户消息发布到消息队列。

Let's take a look on how user input is being processed:

我们来看看如何处理用户输入:

1. User taps the screen                                      |  User input
2. Operating system puts a message in message queue          |  Operating system
3. WPF internals pick up the message                         \
4. WPF internals processes the message                        | WPF internals
5. WPF causes parts of application code to be run:           /
    a) As immediate reactions on events                      \  This is where call may
    b) As an effect of dependency properties being changed   /  be scheduled
6. The application code finishes                             |  Application code
7. The WPF internals finishes their work                     |  WPF internals
   *** This is where I want the scheduled method to run ***
8. WPF peeks for next message from message queue             |  WPF internals

How may I schedule call, such that it will happen in the place I want it to?

我如何安排电话,以便它会发生在我想要的地方?

3 个解决方案

#1


0  

If I understand your problem correctly then this is how I would solve it.

如果我理解你的问题,那么我就是这样解决的。

  1. Declare 2 global variables:

    声明2个全局变量:

    Action<object> gPostProcessingMethod = null;//it must be accessible to any of the methods
                           // that may decide to schedule post-processing of your message
    object gDataForPostProcessing = null;//it will hold a data for post-processing (if any)
    
  2. I assume you have a loop somewhere that is polling your message queue. Let's assume this is while loop. Then it should look something like this to handle the post-processing of your messages:

    我假设你有一个循环在某个地方轮询你的消息队列。我们假设这是while循环。然后它应该看起来像这样处理你的消息的后处理:

        while (...)
        {
            // 1. Your code to dequeue/get next message:
            // .................................
            gPostProcessingMethod= null;
            gDataForPostProcessing = null;
            /* 2. Your code that triggers processing of the message. As far as I understand,
                  this triggering method does not return until all of the subsequently called
                  methods are done.
                  However, as you described, any of those methods may decide to schedule 
                  "post-processing" method that must start at the moment the processing is complete.
                  This is how the scheduling should be done: 
                      gPostProcessingMethod = <AnyMethodThatCompliesWithSignatureOfAction>  
                      gDataForPostProcessing = ...;
            */
    
    
            if (gPostProcessingMethod != null)
            {//You mentioned that this call MUST happen synchronously (otherwise you may use ThreadPool, etc.)
                 gPostProcessingMethod(gDataForPostProcessing);
            }
            // 3. Your remaining code in the loop:
            // ......................................
    
        }
    
  3. Since every subsequent processing method can overwrite values that previous ones assigned to gPostProcessingMethod and gDataForPostProcessing, you should either accept that downstream methods have priority or contrary: forbid changing these variables if they have been set already.

    由于每个后续处理方法都可以覆盖先前分配给gPostProcessingMethod和gDataForPostProcessing的值,因此您应该接受下游方法具有优先级或相反:如果已经设置了这些变量,则禁止更改这些变量。

#2


0  

There are lots of ways to make this work. My personal preference to implement this type of behavior is to use a ConcurrentQueue<>

有很多方法可以完成这项工作。我个人倾向于实现这种行为是使用ConcurrentQueue <>

#3


-1  

You can use semaphores for multithreading, or when singlethread just an int that gets increased on your method start and decrase on method end. You simply wait until this is back to zero.

您可以使用信号量进行多线程处理,或者当单线程只使用在方法开始时增加的int并在方法结束时减少。你只需等到它回到零。

#1


0  

If I understand your problem correctly then this is how I would solve it.

如果我理解你的问题,那么我就是这样解决的。

  1. Declare 2 global variables:

    声明2个全局变量:

    Action<object> gPostProcessingMethod = null;//it must be accessible to any of the methods
                           // that may decide to schedule post-processing of your message
    object gDataForPostProcessing = null;//it will hold a data for post-processing (if any)
    
  2. I assume you have a loop somewhere that is polling your message queue. Let's assume this is while loop. Then it should look something like this to handle the post-processing of your messages:

    我假设你有一个循环在某个地方轮询你的消息队列。我们假设这是while循环。然后它应该看起来像这样处理你的消息的后处理:

        while (...)
        {
            // 1. Your code to dequeue/get next message:
            // .................................
            gPostProcessingMethod= null;
            gDataForPostProcessing = null;
            /* 2. Your code that triggers processing of the message. As far as I understand,
                  this triggering method does not return until all of the subsequently called
                  methods are done.
                  However, as you described, any of those methods may decide to schedule 
                  "post-processing" method that must start at the moment the processing is complete.
                  This is how the scheduling should be done: 
                      gPostProcessingMethod = <AnyMethodThatCompliesWithSignatureOfAction>  
                      gDataForPostProcessing = ...;
            */
    
    
            if (gPostProcessingMethod != null)
            {//You mentioned that this call MUST happen synchronously (otherwise you may use ThreadPool, etc.)
                 gPostProcessingMethod(gDataForPostProcessing);
            }
            // 3. Your remaining code in the loop:
            // ......................................
    
        }
    
  3. Since every subsequent processing method can overwrite values that previous ones assigned to gPostProcessingMethod and gDataForPostProcessing, you should either accept that downstream methods have priority or contrary: forbid changing these variables if they have been set already.

    由于每个后续处理方法都可以覆盖先前分配给gPostProcessingMethod和gDataForPostProcessing的值,因此您应该接受下游方法具有优先级或相反:如果已经设置了这些变量,则禁止更改这些变量。

#2


0  

There are lots of ways to make this work. My personal preference to implement this type of behavior is to use a ConcurrentQueue<>

有很多方法可以完成这项工作。我个人倾向于实现这种行为是使用ConcurrentQueue <>

#3


-1  

You can use semaphores for multithreading, or when singlethread just an int that gets increased on your method start and decrase on method end. You simply wait until this is back to zero.

您可以使用信号量进行多线程处理,或者当单线程只使用在方法开始时增加的int并在方法结束时减少。你只需等到它回到零。