Synchroniczna metoda biblioteki (COM) wywołana poprzez asynchroniczny Task

0

Witam.
Próbuje rozgryźć pewien problem na jaki się natknąłem ostatnio. Oprogramowanie jakie napisałem służy do rozsyłania powiadomień o dokumentach, płatnościach, raportach sprzedaży z Comarch Optima. Niektórzy klienci życzą sobie, aby dokument w postaci PDF pojawił się w załączniku, więc taki dokument "drukuje" Optimą za pomocą obiektów COM jakie Comarch udostępnia partnerom. Problem zaczyna gdy wątki Quartz się "nakładają", są uruchamiane o tej samej porze. Przykład:

  1. Dokumenty WZ - co 15 minut
  2. Dokumenty FA/FV - raz dziennie o 11:15

W momencie gdy system próbuje się zalogować do Optimy i wydrukować dokumenty WZ oraz FA/FV dostaje błąd
Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done.

STACKTRACE

   at CDNBase.ApplicationClass.Login(Object vUser, Object vChk, Object vFirm, Object _ModulKP, Object _ModulKH, Object _ModulKHP, Object _ModulST, Object _ModulFA, Object _ModulMAG, Object _ModulPK, Object _ModulPKXL, Object _ModulCRM, Object _ModulANL, Object _ModulDET, Object _ModulBIU, Object _ModulSRW, Object _ModulOBD, Object _ModulKB, Object _ModulKBP, Object _ModulHAP, Object _ModulCRMP)
   at Optima.Common.OptimaAccess.Login(String oper, String password, String company, Byte[] modules, Object logManager)
   at CallSite.Target(Closure , CallSite , IOptimaAccess , String , String , String , Byte[] , Object )
   at Optima.Common.Logic.Services.LoginService.Login(String oper, String password, String company, ModuleCollection modules)

Wsparcie techniczne z Comarchu twierdzi, że ich system nie jest przystosowany do asynchronicznych operacji i jeden wątek logowania musi być zakończony, aby móc stworzyć kolejny w obrębie jednego procesu.

Czy ja ze swojej strony jestem w stanie to jakoś ominąć? Błąd sugeruje, że to provider bazy danych nie pozwala na asynchroniczność, a nie sama Optima i jej obiekty COM.

1

Jedyne, co mi do głowy przychodzi, to tak zmodyfikować ConnectionString, żeby dodać:
MultipleActiveResultSets=True

Nie mam bladego pojęcia, czy to pomoże. Raczej powinieneś chyba sprawdzać, czy już zakończyłeś jedną operację, zanim zaczniesz drugą. Może i nie będzie dokładnie o 11:15, ale czy kilka minut robi komuś aż tak wielką różnicę? To może być nawet kilka sekund. Zależy, co robisz.

0

Teoretycznie mam właśnie dwie opcje:

  1. Tak jak mówisz, zaczekać aż się skończy jeden wątek i wtedy dopiero zacząć drugi za pomocą @DisallowConcurrentExecution is an annotation that can be added to the Job class that tells Quartz not to execute multiple instances of a given job definition
  2. Zalogować się przed wywołaniem wątku, na start usługi, i puścić obiekt sesji do funkcji public async Task Execute(IJobExecutionContext context). I tak do drukowania dokumentów nie potrzebuje licencji, więc mogę być zalogowany przez cały czas pracy programu.

Kilka minut raczej nikomu krzywdy nie zrobi. Fakt faktem drukowanie dokumentów trwa najdłużej. W przypadku takich 40 faktur dziennie timer może wydłużyć się o więcej niż "parę minut".

1

Hej,

Trochę siedzę w Comarch, więc to Co oni twierdzą to faktycznie jest tak że ich API jest tylko jednowątkowe. Żeby to jakoś ominąć to partnerzy piszę servis który za pomocą kolejek przetwarza po kolei requesty i wtedy nie ma problemu.

Albo tak jak ktoś wyżej zasugerował, zrób to według taksów aby wykonywały się po zakończeniu każdego kolejnego.

Pozdrawiam.

0

Nie ma problemu aby samemu utworzyć kolejkę żądań

0

Może poszukaj o STA Thread web api. Jest trochę info. U mnie aplikacja musiała mieć zwrotkę z numerem dokumentu wiwc nie chcialem kolejkowac. Mam winservice z selfhost api i jakoś działa z XL api.

Edit. Jeśli to nie jest na żądanie użytkownika to chyba lepiej kolejkować zadania.

0

Ja wiem, że raczej nikomu się krzywda nie stanie jak dostanie dokument 30 minut później, albo nawet godzinę. Biorąc pod uwagę, że klient nie wie, o której dostanie dokument. Drażni mnie sam fakt, że muszę się pocić i kombinować bo Comarch jest w technologicznej dziurze i woli dopisywać nowe do starego niż ulepszyć/zaktualizować stare.

Ktoś jest w stanie mi podpowiedzieć jak kolejkować w Quartz? Próbowałem, ale nie pomogło:
quartznet/src/Quartz/Listener/JobChainingJobListener.cs

Jedyne co na tę chwilę zadziałało to to co pisałem wyżej @DisallowConcurrentExecution, ale... Powoduje to, że trigger, który został wywołany wcześniej ma pierwszeństwo i nie wywołuje tego co się nakłada. W moim przypadku pierwsze były faktury (raz dziennie o 11:15), ale jak ktoś zrobi odwrotnie to mi się faktury nigdy się nie wyślą bo pierwszeństwo będzie miały WZ co 15 minut...

0

Ja od doświadczonych w Comarchu ludzi usłyszałem kiedyś, że trzeba wrzucić info o zadaniu do bazy (Tu jak sadze Quartz) i jakis tradycyjny, jednowatkowy winservice sprawdza baze i jak cos jest nowego to coś tam robi. Webapi wtedy dodaję tylko informacje o zadaniach do bazy A sama realizacje jest w winserwisie.

0

Z doświadczenia to co stosowalismy to:

  1. WCF serwis który po MQ przetwarzał zadania.
  2. Dodawanie zadań do bazy i jakaś aplikacja serwis który cyklicznie realizował zadania po kolei.

W innych przypadkach zdarzały się deadlocki itp.

0

Wszyscy piszą o tym samym, a ja właśnie taki system potrzebuje i taki system stworzyłem, ale... Najprawdopodobniej wszystko psuje Quartz, który nie kolejkuje tych zadań ze względu na swoją asynchroniczność, a to kolejkowanie jest wymagane przez Optime. Czy będę zadania wpisywał do bazy, czy do pliku to akurat jest wszystko jedno.
Mam aplikację okienkową do konfigurowania zadań i winservice w tle do wykonywania ich w ustawionym czasie. Chce, aby opcja wywoływania zadań w tym samym czasie została dla zadań niekorzystających z Optimy, np.: płatności i raporty, a zadania typu dokumenty niech się kolejkują w momencie gdy się nakładają.

0

Mam pytanie. Dlaczego nikt nie zaproponował czegoś takiego:

Pobieranie danych do maila

lock(cos){
 operacja optimy na pobranie pdf
}

wysłanie maila

To jest złe rozwiązanie?

Zakładam, że autor pobiera dane do faktury bezpośrednio z bazy danych a optimy potrzebuje tylko do wygenerowania pdfa

1 użytkowników online, w tym zalogowanych: 0, gości: 1