2

I know this has been answered before but I am stuck. I have this class,

public class Job : IJob
{
    public void Execute(IJobExecutionContext context)
    {

    }
}

and I want to call this method which is inside another class:

namespace MySync
{
  public partial class Sync1 : Form
  {
      public void startSync()
      {
         // ...

How do I access the startSync() ? Making it static doesn't help cause there are textbox and such inside.

G90
  • 115
  • 1
  • 7
  • You need an instance of `Sync1`. How are both classes related? You are in `IJob.Execute` and want to call `startSync`. Does `Sync1` call `Execute`? – Tim Schmelter Feb 17 '16 at 12:11
  • Execute runs according to a scheduler, Quartz.Net. Every day, once. – G90 Feb 17 '16 at 12:14
  • Pretty weird use case. You start a delayed task that needs to run in separate process _asynchronously_ and update UI. Most probably your UI will not be even running when task is executed (not saying that's a separate process on other machine :) ), then what your task should do? It looks like you are doing something completely wrong. – Volodymyr Usarskyy Feb 17 '16 at 12:33
  • @VolodymyrUsarskyy I'm sure it's wrong. There is a method that creates some zip files and streams them to a remote machine. I need to schedule this. At the moment this method is on UI because it's easy to write to a textbox and inform the user. I could create a different class but then i would have to use the UI components and that's what i'm searching for how. – G90 Feb 17 '16 at 17:06
  • @G90 Now I am totally confused :) Is your ZIP sent synchronously _or_ it is so difficult to generate it that you need to use scheduler (i.e., process outside of UI) in order not to block UI? "but then i would have to use the UI components and that's what i'm searching for how" - this I didn't understand at all. Could you explain in more details which UI components do you need? – Volodymyr Usarskyy Feb 17 '16 at 17:51
  • @G90 if you use Quartz.NET just to execute zipping in different thread in order not to block UI then I would recommend to take a look on "Thread" or "Task" types. They will run your code async and from other thread (_within_ same process) you can easily update UI components. Using Quartz.NET does not make sense, it was designed to be executed without any interaction with UI. – Volodymyr Usarskyy Feb 17 '16 at 17:58
  • @VolodymyrUsarskyy I am using Quartz.Net because i need to schedule code to run at certain times of day. Can I achieve the same using Task or Thread? – G90 Feb 17 '16 at 18:28
  • @G90 I think you are totally confused. I hope I managed to explain why your approach is not good in my answer below. I hope it will help you to find a right solution. – Volodymyr Usarskyy Feb 17 '16 at 21:00
  • @VolodymyrUsarskyy Hey I am not toootally confused. I'm just only using experiece to get there. :D I'll commented on your post. – G90 Feb 18 '16 at 12:18

5 Answers5

1

your startSync method is contained in a class Sync which is a FORM. You rather refactor and extract that method in a separate class and call that using a instance of that class like

public class Syncclass
{
      public void startSync()
      { 
            // your staff here
      }           
}


public class Job : IJob
{
   private Syncclass sync = null;
    public void Execute(IJobExecutionContext context)
    {
      sync.startSync();
    }

public Job()
{
  sync = new Syncclass();
}
}
Rahul
  • 76,197
  • 13
  • 71
  • 125
1

My answer is based on author's comments under the question.

Now it finally became clear what author tries to achieve and what he is doing wrong :) Author is using Quartz.NET to schedule sending of a ZIP package on regular basis. After package was sent author wants to update a textbox inside user's WinForms app with status like "Congrats! ZIP was sent" What he obviously fails to understand is how delayed jobs (in particular, Quartz.NET) and .NET memory model works.

So, author has two possibilities:

  1. run Quartz.NET inside his WinForms app. It is possible but not typical because it does not make any sense.
  2. run Quartz.NET as standalone service. This is typical usage. Service runs 24x7, app is launched whenever needed.

In first case we have just one windows process and AppDomain (obviously, app will need to run 24x7 in order to be able to sent ZIPs on regular basis; delayed jobs are not executed when app is closed), so communication between two object instances is not a problem. Now lets assume that author solved job serialization issue (job is saved, for example, in MongoDB before execution) and Quartz.NET engine could acquire instance of Sync1 form object. What does he get in result? Exactly! He gets very expensive Task.Run(() => { });. It would be a lot easier to write simple in-process scheduler by yourself :)

In second case Quartz.NET runs as standalone service (so, two windows processes on one or two different machines). Because .NET is so good/bad it will not allow us to simply reference an object from another process, that is why delayed job will NEVER be able to update text box in author's Sync1 form. Solutions that were offered here will create new instance of Sync1 type that has nothing to do with instance in his WinForms app.

Summary for lazy developers: @G90 will not be able to implement what he wants because it is either against Quartz.NET design or against .NET Framework. In order to get it working as he wants, he will have to setup Quartz.NET like is described is second case. Then WinForms application will have to query job status every few minutes and update Sync1 form by itself. It is quite easy to implement, Google and SO will help you to find examples.

  • I think I'm gonna go with the first option. How about this one? http://taskscheduler.codeplex.com/ – G90 Feb 18 '16 at 12:14
  • I've never used this lib and unfortunately can't help you here. But in fact it is second option :) This library just hides part of the setup process and (probably) checks task status by itself. – Volodymyr Usarskyy Feb 18 '16 at 12:41
  • Ok I read about c# schedulers. Should I just create a timer and check for the time every hour? Is there a librady I could use? First option seems easier. – G90 Feb 19 '16 at 08:39
  • if your app runs 24x7 then simple timer-based implementation makes sense. Check time difference between now and next execution time when app starts, create timer (btw, don't forget to reschedule after timer goes off!) and that's all :) You can use any of the .NET timer types – Volodymyr Usarskyy Feb 19 '16 at 09:20
  • I used this example http://stackoverflow.com/a/12535731/5940262 and inside `OnTimedEvent` I have `Sync1 mySyc = new Sync1();` `mySyc.startSync();` and whenever it ticks there is a new program created... I need to call `startSync` but `OnTimedEvent` is static. – G90 Feb 19 '16 at 09:50
  • I don't know how you app is structured but if you have just one Sync1 form that is always opened then you should place timer inside your Sync1 form. In this case you don't have to create new instance of Sync1. From the example that you have used: OnTimedEvent is static because author used console application for a demonstration, this method ca be non-static as well. – Volodymyr Usarskyy Feb 19 '16 at 10:07
  • Well, I went where I didn't want to go because I am not familiar. I used delegate and it works. Finished with the time and seems to be working perfect! Thank you!!! – G90 Feb 19 '16 at 12:31
0
public class Job : IJob
{
    public Sync1 Sync{get;set;};

    public void Execute(IJobExecutionContext context)
    {
          if(Sync!=null)
              Sync.startSync();
    }
}

and when instantiating a job

...
var job=new Job{Sync=**yourSync1Instance**};
...
Yuval Perelman
  • 4,499
  • 1
  • 22
  • 32
0

If you can't make a static class you have to implement some mechanism to share an instance of Sync1 to be able to operate on it.
For example:

public static class SyncShare
{
    public static Sync1 Instance { get; set; }
}

Now you have to assign your Sync1 instance to SyncShare.Instance in some way so that you can use it from any other class.
Please pay attention to your specific needs as the example above is a really basic one without any additional security checks.

TorbenJ
  • 4,462
  • 11
  • 47
  • 84
0

As your Sync1 Form isn't staicyou need to get an Instance of it first. Try the following:

public class Job : IJob
{
     public void Execute(IJobExecutionContext context)
     {
         MySync.Sync1 form = new MySync.Sync1();
         form.startSync();
     }
}
Felix D.
  • 4,811
  • 8
  • 38
  • 72